lsp.lua (54633B)
1 local api = vim.api 2 local validate = vim.validate 3 4 local lsp = vim._defer_require('vim.lsp', { 5 _capability = ..., --- @module 'vim.lsp._capability' 6 _changetracking = ..., --- @module 'vim.lsp._changetracking' 7 _folding_range = ..., --- @module 'vim.lsp._folding_range' 8 _snippet_grammar = ..., --- @module 'vim.lsp._snippet_grammar' 9 _tagfunc = ..., --- @module 'vim.lsp._tagfunc' 10 _watchfiles = ..., --- @module 'vim.lsp._watchfiles' 11 buf = ..., --- @module 'vim.lsp.buf' 12 client = ..., --- @module 'vim.lsp.client' 13 codelens = ..., --- @module 'vim.lsp.codelens' 14 completion = ..., --- @module 'vim.lsp.completion' 15 diagnostic = ..., --- @module 'vim.lsp.diagnostic' 16 document_color = ..., --- @module 'vim.lsp.document_color' 17 handlers = ..., --- @module 'vim.lsp.handlers' 18 inlay_hint = ..., --- @module 'vim.lsp.inlay_hint' 19 inline_completion = ..., --- @module 'vim.lsp.inline_completion' 20 linked_editing_range = ..., --- @module 'vim.lsp.linked_editing_range' 21 log = ..., --- @module 'vim.lsp.log' 22 on_type_formatting = ..., --- @module 'vim.lsp.on_type_formatting' 23 protocol = ..., --- @module 'vim.lsp.protocol' 24 rpc = ..., --- @module 'vim.lsp.rpc' 25 semantic_tokens = ..., --- @module 'vim.lsp.semantic_tokens' 26 util = ..., --- @module 'vim.lsp.util' 27 }) 28 29 local log = lsp.log 30 local protocol = lsp.protocol 31 local util = lsp.util 32 local changetracking = lsp._changetracking 33 34 -- Export these directly from rpc. 35 ---@nodoc 36 lsp.rpc_response_error = lsp.rpc.rpc_response_error 37 38 -- TODO improve handling of scratch buffers with LSP attached. 39 40 --- Called by the client when trying to call a method that's not 41 --- supported in any of the servers registered for the current buffer. 42 ---@param method (vim.lsp.protocol.Method.ClientToServer) name of the method 43 function lsp._unsupported_method(method) 44 local msg = string.format( 45 'vim.lsp: method %q is not supported by any server activated for this buffer', 46 method 47 ) 48 log.warn(msg) 49 return msg 50 end 51 52 ---@param workspace_folders string|lsp.WorkspaceFolder[]? 53 ---@return lsp.WorkspaceFolder[]? 54 function lsp._get_workspace_folders(workspace_folders) 55 if type(workspace_folders) == 'table' then 56 return workspace_folders 57 elseif type(workspace_folders) == 'string' then 58 return { 59 { 60 uri = vim.uri_from_fname(workspace_folders), 61 name = workspace_folders, 62 }, 63 } 64 end 65 end 66 67 local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' } 68 69 local format_line_ending = { 70 ['unix'] = '\n', 71 ['dos'] = '\r\n', 72 ['mac'] = '\r', 73 } 74 75 ---@param bufnr integer 76 ---@return string 77 function lsp._buf_get_line_ending(bufnr) 78 return format_line_ending[vim.bo[bufnr].fileformat] or '\n' 79 end 80 81 local client_errors_base = table.maxn(lsp.rpc.client_errors) 82 local client_errors_offset = 0 83 84 local function client_error(name) 85 client_errors_offset = client_errors_offset + 1 86 local index = client_errors_base + client_errors_offset 87 return { [name] = index, [index] = name } 88 end 89 90 --- Error codes to be used with `on_error` from |vim.lsp.start_client|. 91 --- Can be used to look up the string from a the number or the number 92 --- from the string. 93 --- @nodoc 94 lsp.client_errors = vim.tbl_extend( 95 'error', 96 lsp.rpc.client_errors, 97 client_error('BEFORE_INIT_CALLBACK_ERROR'), 98 client_error('ON_INIT_CALLBACK_ERROR'), 99 client_error('ON_ATTACH_ERROR'), 100 client_error('ON_EXIT_CALLBACK_ERROR') 101 ) 102 103 --- Returns full text of buffer {bufnr} as a string. 104 --- 105 ---@param bufnr integer Buffer handle, or 0 for current. 106 ---@return string # Buffer text as string. 107 function lsp._buf_get_full_text(bufnr) 108 local line_ending = lsp._buf_get_line_ending(bufnr) 109 local text = table.concat(api.nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) 110 if vim.bo[bufnr].eol then 111 text = text .. line_ending 112 end 113 return text 114 end 115 116 --- @param client vim.lsp.Client 117 --- @param config vim.lsp.ClientConfig 118 --- @return boolean 119 local function reuse_client_default(client, config) 120 if client.name ~= config.name or client:is_stopped() then 121 return false 122 end 123 124 local config_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir) 125 126 if not config_folders or not next(config_folders) then 127 -- Reuse if the client was configured with no workspace folders 128 local client_config_folders = 129 lsp._get_workspace_folders(client.config.workspace_folders or client.config.root_dir) 130 return not client_config_folders or not next(client_config_folders) 131 end 132 133 for _, config_folder in ipairs(config_folders) do 134 local found = false 135 for _, client_folder in ipairs(client.workspace_folders or {}) do 136 if config_folder.uri == client_folder.uri then 137 found = true 138 break 139 end 140 end 141 if not found then 142 return false 143 end 144 end 145 146 return true 147 end 148 149 --- Creates and initializes a client with the given configuration. 150 --- @param config vim.lsp.ClientConfig Configuration for the server. 151 --- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be 152 --- fully initialized. Use `on_init` to do any actions once 153 --- the client has been initialized. 154 --- @return string? # Error message, if any 155 local function create_and_init_client(config) 156 local ok, res = pcall(require('vim.lsp.client').create, config) 157 if not ok then 158 return nil, res --[[@as string]] 159 end 160 161 local client = assert(res) 162 163 client:initialize() 164 165 return client.id, nil 166 end 167 168 --- @class vim.lsp.Config : vim.lsp.ClientConfig 169 --- 170 --- See `cmd` in [vim.lsp.ClientConfig]. 171 --- See also `reuse_client` to dynamically decide (per-buffer) when `cmd` should be re-invoked. 172 --- @field cmd? string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers, config: vim.lsp.ClientConfig): vim.lsp.rpc.PublicClient 173 --- 174 --- Filetypes the client will attach to, or `nil` for ALL filetypes. To match files by name, 175 --- pattern, or contents, you can define a custom filetype using |vim.filetype.add()|: 176 --- ```lua 177 --- vim.filetype.add({ 178 --- filename = { 179 --- ['my_filename'] = 'my_filetype1', 180 --- }, 181 --- pattern = { 182 --- ['.*/etc/my_file_pattern/.*'] = 'my_filetype2', 183 --- }, 184 --- }) 185 --- vim.lsp.config('…', { 186 --- filetypes = { 'my_filetype1', 'my_filetype2' }, 187 --- } 188 --- ``` 189 --- @field filetypes? string[] 190 --- 191 --- Predicate which decides if a client should be re-used. Used on all running clients. The default 192 --- implementation re-uses a client if name and root_dir matches. 193 --- @field reuse_client? fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean # 194 --- 195 --- [lsp-root_dir()]() 196 --- Decides the workspace root: the directory where the LSP server will base its workspaceFolders, 197 --- rootUri, and rootPath on initialization. The function form must call the `on_dir` callback to 198 --- provide the root dir, or LSP will not be activated for the buffer. Thus a `root_dir()` function 199 --- can dynamically decide per-buffer whether to activate (or skip) LSP. 200 --- See example at |vim.lsp.enable()|. 201 --- @field root_dir? string|fun(bufnr: integer, on_dir:fun(root_dir?:string)) # 202 --- 203 --- [lsp-root_markers]() 204 --- Filename(s) (".git/", "package.json", …) used to decide the workspace root. Unused if `root_dir` 205 --- is defined. The list order decides priority. To indicate "equal priority", specify names in 206 --- a nested list `{ { 'a.txt', 'b.lua' }, ... }`. 207 --- - For each item, Nvim will search upwards (from the buffer file) for that marker, or list of 208 --- markers; search stops at the first directory containing that marker, and the directory is used 209 --- as the root dir (workspace folder). 210 --- - Example: Find the first ancestor directory containing file or directory "stylua.toml"; if not 211 --- found, find the first ancestor containing ".git": 212 --- ``` 213 --- root_markers = { 'stylua.toml', '.git' } 214 --- ``` 215 --- - Example: Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; 216 --- if not found, find the first ancestor containing ".git": 217 --- ``` 218 --- root_markers = { { 'stylua.toml', '.luarc.json' }, '.git' } 219 --- ``` 220 --- 221 --- @field root_markers? (string|string[])[] 222 223 --- Sets the default configuration for an LSP client (or _all_ clients if the special name "*" is 224 --- used). 225 --- 226 --- Can also be accessed by table-indexing (`vim.lsp.config[…]`) to get the resolved config, or 227 --- redefine the config (instead of "merging" with the config chain). 228 --- 229 --- Examples: 230 --- 231 --- - Add root markers for ALL clients: 232 --- ```lua 233 --- vim.lsp.config('*', { 234 --- root_markers = { '.git', '.hg' }, 235 --- }) 236 --- ``` 237 --- - Add capabilities to ALL clients: 238 --- ```lua 239 --- vim.lsp.config('*', { 240 --- capabilities = { 241 --- textDocument = { 242 --- semanticTokens = { 243 --- multilineTokenSupport = true, 244 --- } 245 --- } 246 --- } 247 --- }) 248 --- ``` 249 --- - Add root markers and capabilities for "clangd": 250 --- ```lua 251 --- vim.lsp.config('clangd', { 252 --- root_markers = { '.clang-format', 'compile_commands.json' }, 253 --- capabilities = { 254 --- textDocument = { 255 --- completion = { 256 --- completionItem = { 257 --- snippetSupport = true, 258 --- } 259 --- } 260 --- } 261 --- } 262 --- }) 263 --- ``` 264 --- - (Re-)define the "clangd" configuration (overrides the resolved chain): 265 --- ```lua 266 --- vim.lsp.config.clangd = { 267 --- cmd = { 268 --- 'clangd', 269 --- '--clang-tidy', 270 --- '--background-index', 271 --- '--offset-encoding=utf-8', 272 --- }, 273 --- root_markers = { '.clangd', 'compile_commands.json' }, 274 --- filetypes = { 'c', 'cpp' }, 275 --- } 276 --- ``` 277 --- - Get the resolved configuration for "lua_ls": 278 --- ```lua 279 --- local cfg = vim.lsp.config.lua_ls 280 --- ``` 281 --- 282 ---@since 13 283 --- 284 --- @param name string 285 --- @param cfg vim.lsp.Config 286 --- @diagnostic disable-next-line:assign-type-mismatch 287 function lsp.config(name, cfg) 288 local _, _ = name, cfg -- ignore unused 289 -- dummy proto for docs 290 end 291 292 lsp._enabled_configs = {} --- @type table<string,{resolved_config:vim.lsp.Config?}> 293 294 --- If a config in vim.lsp.config() is accessed then the resolved config becomes invalid. 295 --- @param name string 296 local function invalidate_enabled_config(name) 297 if name == '*' then 298 for _, v in pairs(lsp._enabled_configs) do 299 v.resolved_config = nil 300 end 301 elseif lsp._enabled_configs[name] then 302 lsp._enabled_configs[name].resolved_config = nil 303 end 304 end 305 306 --- @param name any 307 local function validate_config_name(name) 308 validate('name', name, function(value) 309 if type(value) ~= 'string' then 310 return false 311 end 312 if value ~= '*' and value:match('%*') then 313 return false, 'LSP config name cannot contain wildcard ("*")' 314 end 315 return true 316 end, 'non-wildcard string') 317 end 318 319 --- @nodoc 320 --- @class vim.lsp.config 321 --- @field [string] vim.lsp.Config? 322 --- @field package _configs table<string,vim.lsp.Config> 323 lsp.config = setmetatable({ _configs = {} }, { 324 --- @param self vim.lsp.config 325 --- @param name string 326 --- @return vim.lsp.Config? 327 __index = function(self, name) 328 validate_config_name(name) 329 330 local rconfig = lsp._enabled_configs[name] or {} 331 332 if not rconfig.resolved_config then 333 if name == '*' then 334 rconfig.resolved_config = lsp.config._configs['*'] or {} 335 return rconfig.resolved_config 336 end 337 338 -- Resolve configs from lsp/*.lua 339 -- Calls to vim.lsp.config in lsp/* have a lower precedence than calls from other sites. 340 local rtp_config --- @type vim.lsp.Config? 341 for _, v in ipairs(api.nvim_get_runtime_file(('lsp/%s.lua'):format(name), true)) do 342 local config = assert(loadfile(v))() ---@type any? 343 if type(config) == 'table' then 344 --- @type vim.lsp.Config? 345 rtp_config = vim.tbl_deep_extend('force', rtp_config or {}, config) 346 else 347 error(('%s: not a table'):format(v)) 348 end 349 end 350 351 if not rtp_config and not self._configs[name] then 352 return 353 end 354 355 rconfig.resolved_config = vim.tbl_deep_extend( 356 'force', 357 lsp.config._configs['*'] or {}, 358 rtp_config or {}, 359 self._configs[name] or {} 360 ) 361 rconfig.resolved_config.name = name 362 end 363 364 return rconfig.resolved_config 365 end, 366 367 --- @param self vim.lsp.config 368 --- @param name string 369 --- @param cfg vim.lsp.Config 370 __newindex = function(self, name, cfg) 371 validate_config_name(name) 372 local msg = ('table (hint: to resolve a config, use vim.lsp.config["%s"])'):format(name) 373 validate('cfg', cfg, 'table', msg) 374 invalidate_enabled_config(name) 375 self._configs[name] = cfg 376 end, 377 378 --- @param self vim.lsp.config 379 --- @param name string 380 --- @param cfg vim.lsp.Config 381 __call = function(self, name, cfg) 382 validate_config_name(name) 383 local msg = ('table (hint: to resolve a config, use vim.lsp.config["%s"])'):format(name) 384 validate('cfg', cfg, 'table', msg) 385 invalidate_enabled_config(name) 386 self[name] = vim.tbl_deep_extend('force', self._configs[name] or {}, cfg) 387 end, 388 }) 389 390 local lsp_enable_autocmd_id --- @type integer? 391 392 local function validate_cmd(v) 393 if type(v) == 'table' then 394 if vim.fn.executable(v[1]) == 0 then 395 return false, v[1] .. ' is not executable' 396 end 397 return true 398 end 399 return type(v) == 'function' 400 end 401 402 --- @param config vim.lsp.Config 403 local function validate_config(config) 404 validate('cmd', config.cmd, validate_cmd, 'expected function or table with executable command') 405 validate('reuse_client', config.reuse_client, 'function', true) 406 validate('filetypes', config.filetypes, 'table', true) 407 end 408 409 --- Returns true if: 410 --- 1. the config is managed by vim.lsp, 411 --- 2. it applies to the given buffer, and 412 --- 3. its config is valid (in particular: its `cmd` isn't broken). 413 --- 414 --- @param bufnr integer 415 --- @param config vim.lsp.Config 416 --- @param logging boolean 417 local function can_start(bufnr, config, logging) 418 assert(config) 419 if 420 type(config.filetypes) == 'table' 421 and not vim.tbl_contains(config.filetypes, vim.bo[bufnr].filetype) 422 then 423 return false 424 end 425 426 local config_ok, err = pcall(validate_config, config) 427 if not config_ok then 428 if logging then 429 log.error(('invalid "%s" config: %s'):format(config.name, err)) 430 end 431 return false 432 end 433 434 return true 435 end 436 437 --- @param bufnr integer 438 --- @param config vim.lsp.Config 439 local function start_config(bufnr, config) 440 return vim.lsp.start(config, { 441 bufnr = bufnr, 442 reuse_client = config.reuse_client, 443 _root_markers = config.root_markers, 444 }) 445 end 446 447 --- @param bufnr integer 448 local function lsp_enable_callback(bufnr) 449 -- Only ever attach to buffers that represent an actual file. 450 if vim.bo[bufnr].buftype ~= '' then 451 return 452 end 453 454 -- Stop any clients that no longer apply to this buffer. 455 local clients = lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) 456 for _, client in ipairs(clients) do 457 -- Don't index into lsp.config[…] unless is_enabled() is true. 458 if 459 lsp.is_enabled(client.name) 460 -- Check that the client is managed by vim.lsp.config before deciding to detach it! 461 and lsp.config[client.name] 462 and not can_start(bufnr, lsp.config[client.name], false) 463 then 464 lsp.buf_detach_client(bufnr, client.id) 465 end 466 end 467 468 -- Start any clients that apply to this buffer. 469 for name in vim.spairs(lsp._enabled_configs) do 470 local config = lsp.config[name] 471 if config and can_start(bufnr, config, true) then 472 -- Deepcopy config so changes done in the client 473 -- do not propagate back to the enabled configs. 474 config = vim.deepcopy(config) 475 476 if type(config.root_dir) == 'function' then 477 ---@param root_dir string 478 config.root_dir(bufnr, function(root_dir) 479 config.root_dir = root_dir 480 vim.schedule(function() 481 start_config(bufnr, config) 482 end) 483 end) 484 else 485 start_config(bufnr, config) 486 end 487 end 488 end 489 end 490 491 --- Auto-activates LSP in each buffer based on the |lsp-config| `filetypes`, `root_markers`, and 492 --- `root_dir`. 493 --- 494 --- To disable, pass `enable=false`: Stops related clients and servers (force-stops servers after 495 --- a timeout, unless `exit_timeout=false`). 496 --- 497 --- Raises an error under the following conditions: 498 --- - `{name}` is not a valid LSP config name (for example, `'*'`). 499 --- - `{name}` corresponds to an LSP config file which raises an error. 500 --- 501 --- If an error is raised when multiple names are provided, this function will 502 --- have no side-effects; it will not enable/disable any configs, including 503 --- ones which contain no errors. 504 --- 505 --- Examples: 506 --- 507 --- ```lua 508 --- vim.lsp.enable('clangd') 509 --- vim.lsp.enable({'lua_ls', 'pyright'}) 510 --- ``` 511 --- 512 --- Example: To _dynamically_ decide whether LSP is activated, define a |lsp-root_dir()| function 513 --- which calls `on_dir()` only when you want that config to activate: 514 --- 515 --- ```lua 516 --- vim.lsp.config('lua_ls', { 517 --- root_dir = function(bufnr, on_dir) 518 --- if not vim.fn.bufname(bufnr):match('%.txt$') then 519 --- on_dir(vim.fn.getcwd()) 520 --- end 521 --- end 522 --- }) 523 --- ``` 524 --- 525 ---@since 13 526 --- 527 --- @param name string|string[] Name(s) of client(s) to enable. 528 --- @param enable? boolean If `true|nil`, enables auto-activation of the given LSP config on current 529 --- and future buffers. If `false`, disables auto-activation and stops related LSP clients and 530 --- servers (force-stops servers after `exit_timeout` milliseconds). 531 function lsp.enable(name, enable) 532 validate('name', name, { 'string', 'table' }) 533 534 local names = vim._ensure_list(name) --[[@as string[] ]] 535 local configs = {} --- @type table<string,{resolved_config:vim.lsp.Config?}> 536 537 -- Check for errors, and abort with no side-effects if there is one. 538 for _, nm in ipairs(names) do 539 if nm:match('%*') then 540 error('LSP config name cannot contain wildcard ("*")') 541 end 542 543 -- Raise error if `lsp.config[nm]` raises an error, instead of waiting for 544 -- the error to be triggered by `lsp_enable_callback()`. 545 if enable ~= false then 546 configs[nm] = { resolved_config = lsp.config[nm] } 547 end 548 end 549 550 -- Now that there can be no errors, enable/disable all names. 551 for _, nm in ipairs(names) do 552 lsp._enabled_configs[nm] = enable ~= false and configs[nm] or nil 553 end 554 555 if not next(lsp._enabled_configs) then 556 -- If there are no remaining LSPs enabled, remove the enable autocmd. 557 if lsp_enable_autocmd_id then 558 api.nvim_del_autocmd(lsp_enable_autocmd_id) 559 lsp_enable_autocmd_id = nil 560 end 561 else 562 -- Only ever create autocmd once to reuse computation of config merging. 563 lsp_enable_autocmd_id = lsp_enable_autocmd_id 564 or api.nvim_create_autocmd('FileType', { 565 group = api.nvim_create_augroup('nvim.lsp.enable', {}), 566 callback = function(args) 567 lsp_enable_callback(args.buf) 568 end, 569 }) 570 end 571 572 -- Ensure any pre-existing buffers start/stop their LSP clients. 573 if enable ~= false then 574 if (vim.v.vim_did_enter == 1 or vim.fn.did_filetype() == 1) and next(lsp._enabled_configs) then 575 vim.cmd.doautoall('nvim.lsp.enable FileType') 576 end 577 else 578 for _, nm in ipairs(names) do 579 for _, client in ipairs(lsp.get_clients({ name = nm })) do 580 client:stop(client.exit_timeout) 581 end 582 end 583 end 584 end 585 586 --- Checks if the given LSP config is enabled (globally, not per-buffer). 587 --- 588 --- Unlike `vim.lsp.config['…']`, this does not have the side-effect of resolving the config. 589 --- 590 --- @param name string Config name 591 --- @return boolean 592 function lsp.is_enabled(name) 593 return lsp._enabled_configs[name] ~= nil 594 end 595 596 --- @class vim.lsp.start.Opts 597 --- @inlinedoc 598 --- 599 --- Predicate used to decide if a client should be re-used. Used on all 600 --- running clients. The default implementation re-uses a client if it has the 601 --- same name and if the given workspace folders (or root_dir) are all included 602 --- in the client's workspace folders. 603 --- @field reuse_client? fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean 604 --- 605 --- Buffer handle to attach to if starting or re-using a client (0 for current). 606 --- @field bufnr? integer 607 --- 608 --- Whether to attach the client to a buffer (default true). 609 --- If set to `false`, `reuse_client` and `bufnr` will be ignored. 610 --- @field attach? boolean 611 --- 612 --- Suppress error reporting if the LSP server fails to start (default false). 613 --- @field silent? boolean 614 --- 615 --- @field package _root_markers? (string|string[])[] 616 617 --- Create a new LSP client and start a language server or reuses an already 618 --- running client if one is found matching `name` and `root_dir`. 619 --- Attaches the current buffer to the client. 620 --- 621 --- Example: 622 --- 623 --- ```lua 624 --- vim.lsp.start({ 625 --- name = 'my-server-name', 626 --- cmd = {'name-of-language-server-executable'}, 627 --- root_dir = vim.fs.root(0, {'pyproject.toml', 'setup.py'}), 628 --- }) 629 --- ``` 630 --- 631 --- See |vim.lsp.ClientConfig| for all available options. The most important are: 632 --- 633 --- - `name` arbitrary name for the LSP client. Should be unique per language server. 634 --- - `cmd` command string[] or function. 635 --- - `root_dir` path to the project root. By default this is used to decide if an existing client 636 --- should be re-used. The example above uses |vim.fs.root()| to detect the root by traversing 637 --- the file system upwards starting from the current directory until either a `pyproject.toml` 638 --- or `setup.py` file is found. 639 --- - `workspace_folders` list of `{ uri:string, name: string }` tables specifying the project root 640 --- folders used by the language server. If `nil` the property is derived from `root_dir` for 641 --- convenience. 642 --- 643 --- Language servers use this information to discover metadata like the 644 --- dependencies of your project and they tend to index the contents within the 645 --- project folder. 646 --- 647 --- 648 --- To ensure a language server is only started for languages it can handle, 649 --- make sure to call |vim.lsp.start()| within a |FileType| autocmd. 650 --- Either use |:au|, |nvim_create_autocmd()| or put the call in a 651 --- `ftplugin/<filetype_name>.lua` (See |ftplugin-name|) 652 --- 653 --- @since 10 654 --- 655 --- @param config vim.lsp.ClientConfig Configuration for the server. 656 --- @param opts vim.lsp.start.Opts? Optional keyword arguments. 657 --- @return integer? client_id 658 function lsp.start(config, opts) 659 opts = opts or {} 660 local reuse_client = opts.reuse_client or reuse_client_default 661 local bufnr = vim._resolve_bufnr(opts.bufnr) 662 663 if not config.root_dir and opts._root_markers then 664 validate('root_markers', opts._root_markers, 'table') 665 config = vim.deepcopy(config) 666 667 config.root_dir = vim.fs.root(bufnr, opts._root_markers) 668 end 669 670 if 671 not config.root_dir 672 and (not config.workspace_folders or #config.workspace_folders == 0) 673 and config.workspace_required 674 then 675 log.info( 676 ('skipping config "%s": workspace_required=true, no workspace found'):format(config.name) 677 ) 678 return 679 end 680 681 for _, client in pairs(lsp.client._all) do 682 if reuse_client(client, config) then 683 if opts.attach == false then 684 return client.id 685 end 686 687 if lsp.buf_attach_client(bufnr, client.id) then 688 return client.id 689 end 690 return 691 end 692 end 693 694 local client_id, err = create_and_init_client(config) 695 if err then 696 if not opts.silent then 697 vim.notify(err, vim.log.levels.WARN) 698 end 699 return 700 end 701 702 if opts.attach == false then 703 return client_id 704 end 705 706 if client_id and lsp.buf_attach_client(bufnr, client_id) then 707 return client_id 708 end 709 end 710 711 --- Consumes the latest progress messages from all clients and formats them as a string. 712 --- Empty if there are no clients or if no new messages 713 --- 714 ---@return string 715 function lsp.status() 716 local percentage = nil 717 local messages = {} --- @type string[] 718 for _, client in ipairs(vim.lsp.get_clients()) do 719 --- @diagnostic disable-next-line:no-unknown 720 for progress in client.progress do 721 --- @cast progress {token: lsp.ProgressToken, value: lsp.LSPAny} 722 local value = progress.value 723 if type(value) == 'table' and value.kind then 724 local message = value.message and (value.title .. ': ' .. value.message) or value.title 725 messages[#messages + 1] = message 726 if value.percentage then 727 percentage = math.max(percentage or 0, value.percentage) 728 end 729 end 730 -- else: Doesn't look like work done progress and can be in any format 731 -- Just ignore it as there is no sensible way to display it 732 end 733 end 734 local message = table.concat(messages, ', ') 735 if percentage then 736 return string.format('%3d%%: %s', percentage, message) 737 end 738 return message 739 end 740 741 -- Determines whether the given option can be set by `set_defaults`. 742 ---@param bufnr integer 743 ---@param option string 744 ---@return boolean 745 local function is_empty_or_default(bufnr, option) 746 if vim.bo[bufnr][option] == '' then 747 return true 748 end 749 750 local info = api.nvim_get_option_info2(option, { buf = bufnr }) 751 ---@param e vim.fn.getscriptinfo.ret 752 local scriptinfo = vim.tbl_filter(function(e) 753 return e.sid == info.last_set_sid 754 end, vim.fn.getscriptinfo()) 755 756 if #scriptinfo ~= 1 then 757 return false 758 end 759 760 return vim.startswith(scriptinfo[1].name, vim.fn.expand('$VIMRUNTIME')) 761 end 762 763 ---@param client vim.lsp.Client 764 ---@param bufnr integer 765 function lsp._set_defaults(client, bufnr) 766 if 767 client:supports_method('textDocument/definition') and is_empty_or_default(bufnr, 'tagfunc') 768 then 769 vim.bo[bufnr].tagfunc = 'v:lua.vim.lsp.tagfunc' 770 end 771 if 772 client:supports_method('textDocument/completion') and is_empty_or_default(bufnr, 'omnifunc') 773 then 774 vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc' 775 end 776 if 777 client:supports_method('textDocument/rangeFormatting') 778 and is_empty_or_default(bufnr, 'formatprg') 779 and is_empty_or_default(bufnr, 'formatexpr') 780 then 781 vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr()' 782 end 783 vim._with({ buf = bufnr }, function() 784 if 785 client:supports_method('textDocument/hover') 786 and is_empty_or_default(bufnr, 'keywordprg') 787 and vim.fn.maparg('K', 'n', false, false) == '' 788 then 789 vim.keymap.set('n', 'K', function() 790 vim.lsp.buf.hover() 791 end, { buffer = bufnr, desc = 'vim.lsp.buf.hover()' }) 792 end 793 end) 794 if client:supports_method('textDocument/diagnostic') then 795 lsp.diagnostic._enable(bufnr) 796 end 797 end 798 799 --- @deprecated 800 --- Starts and initializes a client with the given configuration. 801 --- @param config vim.lsp.ClientConfig Configuration for the server. 802 --- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be 803 --- fully initialized. Use `on_init` to do any actions once 804 --- the client has been initialized. 805 --- @return string? # Error message, if any 806 function lsp.start_client(config) 807 vim.deprecate('vim.lsp.start_client()', 'vim.lsp.start()', '0.13') 808 return create_and_init_client(config) 809 end 810 811 ---Buffer lifecycle handler for textDocument/didSave 812 --- @param bufnr integer 813 local function text_document_did_save_handler(bufnr) 814 bufnr = vim._resolve_bufnr(bufnr) 815 local uri = vim.uri_from_bufnr(bufnr) 816 local text = vim.func._memoize('concat', lsp._buf_get_full_text) 817 for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do 818 local name = api.nvim_buf_get_name(bufnr) 819 local old_name = changetracking._get_and_set_name(client, bufnr, name) 820 if old_name and name ~= old_name then 821 client:notify('textDocument/didClose', { 822 textDocument = { 823 uri = vim.uri_from_fname(old_name), 824 }, 825 }) 826 client:notify('textDocument/didOpen', { 827 textDocument = { 828 version = 0, 829 uri = uri, 830 languageId = client.get_language_id(bufnr, vim.bo[bufnr].filetype), 831 text = lsp._buf_get_full_text(bufnr), 832 }, 833 }) 834 util.buf_versions[bufnr] = 0 835 end 836 local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save') 837 if save_capability then 838 local included_text --- @type string? 839 if type(save_capability) == 'table' and save_capability.includeText then 840 included_text = text(bufnr) 841 end 842 client:notify('textDocument/didSave', { 843 textDocument = { 844 uri = uri, 845 }, 846 text = included_text, 847 }) 848 end 849 end 850 end 851 852 --- @type table<integer,true> 853 local attached_buffers = {} 854 855 --- @param bufnr integer 856 local function buf_attach(bufnr) 857 if attached_buffers[bufnr] then 858 return 859 end 860 attached_buffers[bufnr] = true 861 862 local uri = vim.uri_from_bufnr(bufnr) 863 local augroup = ('nvim.lsp.b_%d_save'):format(bufnr) 864 local group = api.nvim_create_augroup(augroup, { clear = true }) 865 api.nvim_create_autocmd('BufWritePre', { 866 group = group, 867 buffer = bufnr, 868 desc = 'vim.lsp: textDocument/willSave', 869 callback = function(ctx) 870 for _, client in ipairs(lsp.get_clients({ bufnr = ctx.buf })) do 871 local params = { 872 textDocument = { 873 uri = uri, 874 }, 875 reason = protocol.TextDocumentSaveReason.Manual, ---@type integer 876 } 877 if client:supports_method('textDocument/willSave') then 878 client:notify('textDocument/willSave', params) 879 end 880 if client:supports_method('textDocument/willSaveWaitUntil') then 881 local result, err = 882 client:request_sync('textDocument/willSaveWaitUntil', params, 1000, ctx.buf) 883 if result and result.result then 884 util.apply_text_edits(result.result, ctx.buf, client.offset_encoding) 885 elseif err then 886 log.error(vim.inspect(err)) 887 end 888 end 889 end 890 end, 891 }) 892 api.nvim_create_autocmd('BufWritePost', { 893 group = group, 894 buffer = bufnr, 895 desc = 'vim.lsp: textDocument/didSave handler', 896 callback = function(ctx) 897 text_document_did_save_handler(ctx.buf) 898 end, 899 }) 900 -- First time, so attach and set up stuff. 901 api.nvim_buf_attach(bufnr, false, { 902 on_lines = function(_, _, changedtick, firstline, lastline, new_lastline) 903 if #lsp.get_clients({ bufnr = bufnr }) == 0 then 904 -- detach if there are no clients 905 return #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 906 end 907 util.buf_versions[bufnr] = changedtick 908 changetracking.send_changes(bufnr, firstline, lastline, new_lastline) 909 end, 910 911 on_reload = function() 912 local clients = lsp.get_clients({ bufnr = bufnr }) 913 local params = { textDocument = { uri = uri } } 914 for _, client in ipairs(clients) do 915 changetracking.reset_buf(client, bufnr) 916 if client:supports_method('textDocument/didClose') then 917 client:notify('textDocument/didClose', params) 918 end 919 end 920 for _, client in ipairs(clients) do 921 client:_text_document_did_open_handler(bufnr) 922 end 923 end, 924 925 on_detach = function() 926 local clients = lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) 927 for _, client in ipairs(clients) do 928 client:_on_detach(bufnr) 929 end 930 attached_buffers[bufnr] = nil 931 util.buf_versions[bufnr] = nil 932 end, 933 934 -- TODO if we know all of the potential clients ahead of time, then we 935 -- could conditionally set this. 936 -- utf_sizes = size_index > 1; 937 utf_sizes = true, 938 }) 939 end 940 941 --- Implements the `textDocument/did…` notifications required to track a buffer 942 --- for any language server. 943 --- 944 --- Without calling this, the server won't be notified of changes to a buffer. 945 --- 946 ---@param bufnr (integer) Buffer handle, or 0 for current 947 ---@param client_id (integer) Client id 948 ---@return boolean success `true` if client was attached successfully; `false` otherwise 949 function lsp.buf_attach_client(bufnr, client_id) 950 validate('bufnr', bufnr, 'number', true) 951 validate('client_id', client_id, 'number') 952 bufnr = vim._resolve_bufnr(bufnr) 953 if not api.nvim_buf_is_loaded(bufnr) then 954 log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) 955 return false 956 end 957 958 local client = lsp.get_client_by_id(client_id) 959 if not client then 960 return false 961 end 962 963 buf_attach(bufnr) 964 965 if client.attached_buffers[bufnr] then 966 return true 967 end 968 969 client.attached_buffers[bufnr] = true 970 971 -- This is our first time attaching this client to this buffer. 972 -- Send didOpen for the client if it is initialized. If it isn't initialized 973 -- then it will send didOpen on initialize. 974 if client.initialized then 975 client:on_attach(bufnr) 976 end 977 return true 978 end 979 980 --- Detaches client from the specified buffer. 981 --- Note: While the server is notified that the text document (buffer) 982 --- was closed, it is still able to send notifications should it ignore this notification. 983 --- 984 ---@param bufnr integer Buffer handle, or 0 for current 985 ---@param client_id integer Client id 986 function lsp.buf_detach_client(bufnr, client_id) 987 validate('bufnr', bufnr, 'number', true) 988 validate('client_id', client_id, 'number') 989 bufnr = vim._resolve_bufnr(bufnr) 990 991 local client = lsp.get_client_by_id(client_id) 992 if not client or not client.attached_buffers[bufnr] then 993 vim.notify( 994 string.format( 995 'Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', 996 bufnr, 997 client_id 998 ) 999 ) 1000 return 1001 else 1002 client:_on_detach(bufnr) 1003 end 1004 end 1005 1006 --- Checks if a buffer is attached for a particular client. 1007 --- 1008 ---@param bufnr integer Buffer handle, or 0 for current 1009 ---@param client_id integer the client id 1010 function lsp.buf_is_attached(bufnr, client_id) 1011 return lsp.get_clients({ bufnr = bufnr, id = client_id, _uninitialized = true })[1] ~= nil 1012 end 1013 1014 --- Gets a client by id, or nil if the id is invalid or the client was stopped. 1015 --- The returned client may not yet be fully initialized. 1016 --- 1017 ---@param client_id integer client id 1018 --- 1019 ---@return vim.lsp.Client? client rpc object 1020 function lsp.get_client_by_id(client_id) 1021 return lsp.client._all[client_id] 1022 end 1023 1024 --- Returns list of buffers attached to client_id. 1025 --- 1026 ---@deprecated 1027 ---@param client_id integer client id 1028 ---@return integer[] buffers list of buffer ids 1029 function lsp.get_buffers_by_client_id(client_id) 1030 vim.deprecate( 1031 'vim.lsp.get_buffers_by_client_id()', 1032 'vim.lsp.get_client_by_id(id).attached_buffers', 1033 '0.13' 1034 ) 1035 local client = lsp.get_client_by_id(client_id) 1036 return client and vim.tbl_keys(client.attached_buffers) or {} 1037 end 1038 1039 --- Stops a client(s). 1040 --- 1041 --- You can also use the `stop()` function on a |vim.lsp.Client| object. 1042 --- To stop all clients: 1043 --- 1044 --- ```lua 1045 --- vim.lsp.stop_client(vim.lsp.get_clients()) 1046 --- ``` 1047 --- 1048 --- By default asks the server to shutdown, unless stop was requested already for this client (then 1049 --- force-shutdown is attempted, unless `exit_timeout=false`). 1050 --- 1051 ---@deprecated 1052 ---@param client_id integer|integer[]|vim.lsp.Client[] id, list of id's, or list of |vim.lsp.Client| objects 1053 ---@param force? boolean|integer Whether to shutdown forcefully. 1054 --- If `force` is a number, it will be treated as the time in milliseconds to 1055 --- wait before forcing the shutdown. 1056 function lsp.stop_client(client_id, force) 1057 vim.deprecate('vim.lsp.stop_client()', 'vim.lsp.Client:stop()', '0.13') 1058 --- @type integer[]|vim.lsp.Client[] 1059 local ids = type(client_id) == 'table' and client_id or { client_id } 1060 for _, id in ipairs(ids) do 1061 if type(id) == 'table' then 1062 if id.stop then 1063 id:stop(force) 1064 end 1065 else 1066 --- @cast id -vim.lsp.Client 1067 local client = lsp.get_client_by_id(id) 1068 if client then 1069 client:stop(force) 1070 end 1071 end 1072 end 1073 end 1074 1075 --- Key-value pairs used to filter the returned clients. 1076 --- @class vim.lsp.get_clients.Filter 1077 --- @inlinedoc 1078 --- 1079 --- Only return clients with the given id 1080 --- @field id? integer 1081 --- 1082 --- Only return clients attached to this buffer 1083 --- @field bufnr? integer 1084 --- 1085 --- Only return clients with the given name 1086 --- @field name? string 1087 --- 1088 --- Only return clients supporting the given method 1089 --- @field method? vim.lsp.protocol.Method.ClientToServer 1090 --- 1091 --- Also return uninitialized clients. 1092 --- @field package _uninitialized? boolean 1093 1094 --- Get active clients. 1095 --- 1096 ---@since 12 1097 --- 1098 ---@param filter? vim.lsp.get_clients.Filter 1099 ---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects 1100 function lsp.get_clients(filter) 1101 validate('filter', filter, 'table', true) 1102 1103 filter = filter or {} 1104 1105 local clients = {} --- @type vim.lsp.Client[] 1106 1107 local bufnr = filter.bufnr and vim._resolve_bufnr(filter.bufnr) 1108 1109 for _, client in pairs(lsp.client._all) do 1110 if 1111 client 1112 and (filter.id == nil or client.id == filter.id) 1113 and (filter.bufnr == nil or client.attached_buffers[bufnr]) 1114 and (filter.name == nil or client.name == filter.name) 1115 and (filter.method == nil or client:supports_method(filter.method, filter.bufnr)) 1116 and (filter._uninitialized or client.initialized) 1117 then 1118 clients[#clients + 1] = client 1119 end 1120 end 1121 return clients 1122 end 1123 1124 ---@deprecated 1125 function lsp.get_active_clients(filter) 1126 vim.deprecate('vim.lsp.get_active_clients()', 'vim.lsp.get_clients()', '0.12') 1127 return lsp.get_clients(filter) 1128 end 1129 1130 -- Minimum time before warning about LSP exit_timeout on Nvim exit. 1131 local min_warn_exit_timeout = 100 1132 1133 api.nvim_create_autocmd('VimLeavePre', { 1134 desc = 'vim.lsp: exit handler', 1135 callback = function() 1136 local active_clients = lsp.get_clients() 1137 log.info('exit_handler', active_clients) 1138 1139 local max_timeout = 0 1140 for _, client in pairs(active_clients) do 1141 max_timeout = math.max(max_timeout, tonumber(client.exit_timeout) or 0) 1142 client:stop(client.exit_timeout) 1143 end 1144 1145 local exit_warning_timer = max_timeout > min_warn_exit_timeout 1146 and vim.defer_fn(function() 1147 api.nvim_echo({ 1148 { 1149 string.format( 1150 'Waiting %ss for LSP exit (Press Ctrl-C to force exit)', 1151 max_timeout / 1e3 1152 ), 1153 'WarningMsg', 1154 }, 1155 }, true, {}) 1156 end, min_warn_exit_timeout) 1157 1158 vim.wait(max_timeout, function() 1159 return vim.iter(active_clients):all(function(client) 1160 return client.rpc.is_closing() 1161 end) 1162 end) 1163 1164 if exit_warning_timer and not exit_warning_timer:is_closing() then 1165 exit_warning_timer:close() 1166 end 1167 end, 1168 }) 1169 1170 ---@nodoc 1171 --- Sends an async request for all active clients attached to the 1172 --- buffer. 1173 --- 1174 ---@param bufnr (integer) Buffer handle, or 0 for current. 1175 ---@param method (vim.lsp.protocol.Method.ClientToServer.Request) LSP method name 1176 ---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server 1177 ---@param handler? lsp.Handler See |lsp-handler| 1178 --- If nil, follows resolution strategy defined in |lsp-handler-configuration| 1179 ---@param on_unsupported? fun() 1180 --- The function to call when the buffer has no clients that support the given method. 1181 --- Defaults to an `ERROR` level notification. 1182 ---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs 1183 ---for all successful requests. 1184 ---@return function _cancel_all_requests Function which can be used to 1185 ---cancel all the requests. You could instead 1186 ---iterate all clients and call their `cancel_request()` methods. 1187 function lsp.buf_request(bufnr, method, params, handler, on_unsupported) 1188 validate('bufnr', bufnr, 'number', true) 1189 validate('method', method, 'string') 1190 validate('handler', handler, 'function', true) 1191 validate('on_unsupported', on_unsupported, 'function', true) 1192 1193 bufnr = vim._resolve_bufnr(bufnr) 1194 local method_supported = false 1195 local clients = lsp.get_clients({ bufnr = bufnr }) 1196 local client_request_ids = {} --- @type table<integer,integer> 1197 for _, client in ipairs(clients) do 1198 if client:supports_method(method, bufnr) then 1199 method_supported = true 1200 1201 local cparams = type(params) == 'function' and params(client, bufnr) or params --[[@as table?]] 1202 local request_success, request_id = client:request(method, cparams, handler, bufnr) 1203 -- This could only fail if the client shut down in the time since we looked 1204 -- it up and we did the request, which should be rare. 1205 if request_success then 1206 client_request_ids[client.id] = request_id 1207 end 1208 end 1209 end 1210 1211 -- if has client but no clients support the given method, notify the user 1212 if next(clients) and not method_supported then 1213 if on_unsupported == nil then 1214 vim.notify(lsp._unsupported_method(method), vim.log.levels.ERROR) 1215 else 1216 on_unsupported() 1217 end 1218 vim.cmd.redraw() 1219 return {}, function() end 1220 end 1221 1222 local function _cancel_all_requests() 1223 for client_id, request_id in pairs(client_request_ids) do 1224 local client = lsp.get_client_by_id(client_id) 1225 if client and client.requests[request_id] then 1226 client:cancel_request(request_id) 1227 end 1228 end 1229 end 1230 1231 return client_request_ids, _cancel_all_requests 1232 end 1233 1234 --- Sends an async request for all active clients attached to the buffer and executes the `handler` 1235 --- callback with the combined result. 1236 --- 1237 ---@since 7 1238 --- 1239 ---@param bufnr (integer) Buffer handle, or 0 for current. 1240 ---@param method (vim.lsp.protocol.Method.ClientToServer.Request) LSP method name 1241 ---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server. 1242 --- Can also be passed as a function that returns the params table for cases where 1243 --- parameters are specific to the client. 1244 ---@param handler lsp.MultiHandler (function) 1245 --- Handler called after all requests are completed. Server results are passed as 1246 --- a `client_id:result` map. 1247 ---@return function cancel Function that cancels all requests. 1248 function lsp.buf_request_all(bufnr, method, params, handler) 1249 local results = {} --- @type table<integer,{err: lsp.ResponseError?, result: any, context: lsp.HandlerContext}> 1250 local remaining --- @type integer? 1251 1252 local _, cancel = lsp.buf_request(bufnr, method, params, function(err, result, ctx, config) 1253 if not remaining then 1254 -- Calculate as late as possible in case a client is removed during the request 1255 remaining = #lsp.get_clients({ bufnr = bufnr, method = method }) 1256 end 1257 1258 -- The error key is deprecated and will be removed in 0.13 1259 results[ctx.client_id] = { err = err, error = err, result = result, context = ctx } 1260 remaining = remaining - 1 1261 1262 if remaining == 0 then 1263 handler(results, ctx, config) 1264 end 1265 end) 1266 1267 return cancel 1268 end 1269 1270 --- Sends a request to all server and waits for the response of all of them. 1271 --- 1272 --- Calls |vim.lsp.buf_request_all()| but blocks Nvim while awaiting the result. 1273 --- Parameters are the same as |vim.lsp.buf_request_all()| but the result is 1274 --- different. Waits a maximum of {timeout_ms}. 1275 --- 1276 ---@since 7 1277 --- 1278 ---@param bufnr integer Buffer handle, or 0 for current. 1279 ---@param method vim.lsp.protocol.Method.ClientToServer.Request LSP method name 1280 ---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server. 1281 --- Can also be passed as a function that returns the params table for cases where 1282 --- parameters are specific to the client. 1283 ---@param timeout_ms integer? Maximum time in milliseconds to wait for a result. 1284 --- (default: `1000`) 1285 ---@return table<integer, {error: lsp.ResponseError?, result: any}>? result Map of client_id:request_result. 1286 ---@return string? err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. 1287 function lsp.buf_request_sync(bufnr, method, params, timeout_ms) 1288 local request_results ---@type table 1289 1290 local cancel = lsp.buf_request_all(bufnr, method, params, function(it) 1291 request_results = it 1292 end) 1293 1294 local wait_result, reason = vim.wait(timeout_ms or 1000, function() 1295 return request_results ~= nil 1296 end, 10) 1297 1298 if not wait_result then 1299 cancel() 1300 return nil, wait_result_reason[reason] 1301 end 1302 1303 return request_results 1304 end 1305 1306 --- Send a notification to a server 1307 --- 1308 ---@since 7 1309 --- 1310 ---@param bufnr integer? The number of the buffer 1311 ---@param method vim.lsp.protocol.Method.ClientToServer.Notification Name of the request method 1312 ---@param params any Arguments to send to the server 1313 --- 1314 ---@return boolean success true if any client returns true; false otherwise 1315 function lsp.buf_notify(bufnr, method, params) 1316 validate('bufnr', bufnr, 'number', true) 1317 validate('method', method, 'string') 1318 local resp = false 1319 for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do 1320 if client.rpc.notify(method, params) then 1321 resp = true 1322 end 1323 end 1324 return resp 1325 end 1326 1327 --- Implements 'omnifunc' compatible LSP completion. 1328 --- 1329 ---@see |complete-functions| 1330 ---@see |complete-items| 1331 ---@see |CompleteDone| 1332 --- 1333 ---@param findstart integer 0 or 1, decides behavior 1334 ---@param base integer findstart=0, text to match against 1335 --- 1336 ---@return integer|table Decided by {findstart}: 1337 --- - findstart=0: column where the completion starts, or -2 or -3 1338 --- - findstart=1: list of matches (actually just calls |complete()|) 1339 function lsp.omnifunc(findstart, base) 1340 return vim.lsp.completion._omnifunc(findstart, base) 1341 end 1342 1343 --- @class vim.lsp.formatexpr.Opts 1344 --- @inlinedoc 1345 --- 1346 --- The timeout period for the formatting request. 1347 --- (default: 500ms). 1348 --- @field timeout_ms integer 1349 1350 --- Provides an interface between the built-in client and a `formatexpr` function. 1351 --- 1352 --- Currently only supports a single client. This can be set via 1353 --- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` or (more typically) in `on_attach` 1354 --- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`. 1355 --- 1356 ---@param opts? vim.lsp.formatexpr.Opts 1357 function lsp.formatexpr(opts) 1358 opts = opts or {} 1359 local timeout_ms = opts.timeout_ms or 500 1360 1361 if vim.list_contains({ 'i', 'R', 'ic', 'ix' }, vim.fn.mode()) then 1362 -- `formatexpr` is also called when exceeding `textwidth` in insert mode 1363 -- fall back to internal formatting 1364 return 1 1365 end 1366 1367 local start_lnum = vim.v.lnum 1368 local end_lnum = start_lnum + vim.v.count - 1 1369 1370 if start_lnum <= 0 or end_lnum <= 0 then 1371 return 0 1372 end 1373 local bufnr = api.nvim_get_current_buf() 1374 for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do 1375 if client:supports_method('textDocument/rangeFormatting') then 1376 local params = util.make_formatting_params() 1377 local end_line = vim.fn.getline(end_lnum) --[[@as string]] 1378 local end_col = vim.str_utfindex(end_line, client.offset_encoding) 1379 --- @cast params +lsp.DocumentRangeFormattingParams 1380 params.range = { 1381 start = { 1382 line = start_lnum - 1, 1383 character = 0, 1384 }, 1385 ['end'] = { 1386 line = end_lnum - 1, 1387 character = end_col, 1388 }, 1389 } 1390 local response = 1391 client:request_sync('textDocument/rangeFormatting', params, timeout_ms, bufnr) 1392 if response and response.result then 1393 util.apply_text_edits(response.result, bufnr, client.offset_encoding) 1394 return 0 1395 end 1396 end 1397 end 1398 1399 -- do not run builtin formatter. 1400 return 0 1401 end 1402 1403 --- Provides an interface between the built-in client and 'tagfunc'. 1404 --- 1405 --- When used with normal mode commands (e.g. |CTRL-]|) this will invoke 1406 --- the "textDocument/definition" LSP method to find the tag under the cursor. 1407 --- Otherwise, uses "workspace/symbol". If no results are returned from 1408 --- any LSP servers, falls back to using built-in tags. 1409 --- 1410 ---@param pattern string Pattern used to find a workspace symbol 1411 ---@param flags string See |tag-function| 1412 --- 1413 ---@return table[] tags A list of matching tags 1414 function lsp.tagfunc(pattern, flags) 1415 return vim.lsp._tagfunc(pattern, flags) 1416 end 1417 1418 --- Provides an interface between the built-in client and a `foldexpr` function. 1419 --- 1420 --- To use, set 'foldmethod' to "expr" and set the value of 'foldexpr': 1421 --- 1422 --- ```lua 1423 --- vim.o.foldmethod = 'expr' 1424 --- vim.o.foldexpr = 'v:lua.vim.lsp.foldexpr()' 1425 --- ``` 1426 --- 1427 --- Or use it only when supported by checking for the "textDocument/foldingRange" 1428 --- capability in an |LspAttach| autocommand. Example: 1429 --- 1430 --- ```lua 1431 --- vim.o.foldmethod = 'expr' 1432 --- -- Default to treesitter folding 1433 --- vim.o.foldexpr = 'v:lua.vim.treesitter.foldexpr()' 1434 --- -- Prefer LSP folding if client supports it 1435 --- vim.api.nvim_create_autocmd('LspAttach', { 1436 --- callback = function(args) 1437 --- local client = vim.lsp.get_client_by_id(args.data.client_id) 1438 --- if client:supports_method('textDocument/foldingRange') then 1439 --- local win = vim.api.nvim_get_current_win() 1440 --- vim.wo[win][0].foldexpr = 'v:lua.vim.lsp.foldexpr()' 1441 --- end 1442 --- end, 1443 --- }) 1444 --- ``` 1445 --- 1446 ---@param lnum integer line number 1447 function lsp.foldexpr(lnum) 1448 return vim.lsp._folding_range.foldexpr(lnum) 1449 end 1450 1451 --- Close all {kind} of folds in the the window with {winid}. 1452 --- 1453 --- To automatically fold imports when opening a file, you can use an autocmd: 1454 --- 1455 --- ```lua 1456 --- vim.api.nvim_create_autocmd('LspNotify', { 1457 --- callback = function(args) 1458 --- if args.data.method == 'textDocument/didOpen' then 1459 --- vim.lsp.foldclose('imports', vim.fn.bufwinid(args.buf)) 1460 --- end 1461 --- end, 1462 --- }) 1463 --- ``` 1464 --- 1465 ---@since 13 1466 --- 1467 ---@param kind lsp.FoldingRangeKind Kind to close, one of "comment", "imports" or "region". 1468 ---@param winid? integer Defaults to the current window. 1469 function lsp.foldclose(kind, winid) 1470 return vim.lsp._folding_range.foldclose(kind, winid) 1471 end 1472 1473 --- Provides a `foldtext` function that shows the `collapsedText` retrieved, 1474 --- defaults to the first folded line if `collapsedText` is not provided. 1475 function lsp.foldtext() 1476 return vim.lsp._folding_range.foldtext() 1477 end 1478 1479 ---@deprecated Use |vim.lsp.get_client_by_id()| instead. 1480 ---Checks whether a client is stopped. 1481 --- 1482 ---@param client_id integer 1483 ---@return boolean stopped true if client is stopped, false otherwise. 1484 function lsp.client_is_stopped(client_id) 1485 vim.deprecate('vim.lsp.client_is_stopped()', 'vim.lsp.get_client_by_id()', '0.14') 1486 assert(client_id, 'missing client_id param') 1487 return not lsp.get_client_by_id(client_id) 1488 end 1489 1490 --- Gets a map of client_id:client pairs for the given buffer, where each value 1491 --- is a |vim.lsp.Client| object. 1492 --- 1493 ---@param bufnr integer? Buffer handle, or 0 for current 1494 ---@return table result is table of (client_id, client) pairs 1495 ---@deprecated Use |vim.lsp.get_clients()| instead. 1496 function lsp.buf_get_clients(bufnr) 1497 vim.deprecate('vim.lsp.buf_get_clients()', 'vim.lsp.get_clients()', '0.12') 1498 local result = {} --- @type table<integer,vim.lsp.Client> 1499 for _, client in ipairs(lsp.get_clients({ bufnr = vim._resolve_bufnr(bufnr) })) do 1500 result[client.id] = client 1501 end 1502 return result 1503 end 1504 1505 --- Log level dictionary with reverse lookup as well. 1506 --- 1507 --- Can be used to lookup the number from the name or the 1508 --- name from the number. 1509 --- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" 1510 --- Level numbers begin with "TRACE" at 0 1511 --- @nodoc 1512 lsp.log_levels = log.levels 1513 1514 --- Sets the global log level for LSP logging. 1515 --- 1516 --- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" 1517 --- 1518 --- Level numbers begin with "TRACE" at 0 1519 --- 1520 --- Use `lsp.log_levels` for reverse lookup. 1521 --- 1522 ---@deprecated 1523 ---@see |vim.lsp.log_levels| 1524 --- 1525 ---@param level (integer|string) the case insensitive level name or number 1526 function lsp.set_log_level(level) 1527 vim.deprecate('vim.lsp.set_log_level()', 'vim.lsp.log.set_level()', '0.13') 1528 1529 if type(level) == 'string' or type(level) == 'number' then 1530 log.set_level(level) 1531 else 1532 error(string.format('Invalid log level: %q', level)) 1533 end 1534 end 1535 1536 --- Gets the path of the logfile used by the LSP client. 1537 --- 1538 ---@deprecated 1539 ---@return string path to log file 1540 function lsp.get_log_path() 1541 vim.deprecate('vim.lsp.get_log_path()', 'vim.lsp.log.get_filename()', '0.13') 1542 1543 return log.get_filename() 1544 end 1545 1546 ---@nodoc 1547 --- Invokes a function for each LSP client attached to a buffer. 1548 --- 1549 ---@param bufnr integer Buffer number 1550 ---@param fn function Function to run on each client attached to buffer 1551 --- {bufnr}. The function takes the client, client ID, and 1552 --- buffer number as arguments. 1553 ---@deprecated use lsp.get_clients({ bufnr = bufnr }) with regular loop 1554 function lsp.for_each_buffer_client(bufnr, fn) 1555 vim.deprecate( 1556 'vim.lsp.for_each_buffer_client()', 1557 'lsp.get_clients({ bufnr = bufnr }) with regular loop', 1558 '0.12' 1559 ) 1560 bufnr = vim._resolve_bufnr(bufnr) 1561 1562 for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do 1563 fn(client, client.id, bufnr) 1564 end 1565 end 1566 1567 --- @deprecated 1568 --- Function to manage overriding defaults for LSP handlers. 1569 ---@param handler (lsp.Handler) See |lsp-handler| 1570 ---@param override_config (table) Table containing the keys to override behavior of the {handler} 1571 function lsp.with(handler, override_config) 1572 vim.deprecate( 1573 'vim.lsp.with()', 1574 'Pass the configuration to equivalent functions in `vim.lsp.buf`', 1575 '0.12' 1576 ) 1577 return function(err, result, ctx, config) 1578 return handler(err, result, ctx, vim.tbl_deep_extend('force', config or {}, override_config)) 1579 end 1580 end 1581 1582 --- Map of client-defined handlers implementing custom (off-spec) commands which a server may 1583 --- invoke. Each key is a unique command name; each value is a function which is called when an LSP 1584 --- action (code action, code lenses, …) requests it by name. 1585 --- 1586 --- If an LSP response requests a command not defined client-side, Nvim will forward it to the 1587 --- server as `workspace/executeCommand`. 1588 --- 1589 --- - Argument 1 is the `Command`: 1590 --- ``` 1591 --- Command 1592 --- title: String 1593 --- command: String 1594 --- arguments?: any[] 1595 --- ``` 1596 --- - Argument 2 is the |lsp-handler| `ctx`. 1597 --- 1598 --- Example: 1599 --- 1600 --- ```lua 1601 --- vim.lsp.commands['java.action.generateToStringPrompt'] = function(_, ctx) 1602 --- require("jdtls.async").run(function() 1603 --- local _, result = request(ctx.bufnr, 'java/checkToStringStatus', ctx.params) 1604 --- local fields = ui.pick_many(result.fields, 'Include item in toString?', function(x) 1605 --- return string.format('%s: %s', x.name, x.type) 1606 --- end) 1607 --- local _, edit = request(ctx.bufnr, 'java/generateToString', { context = ctx.params; fields = fields; }) 1608 --- vim.lsp.util.apply_workspace_edit(edit, offset_encoding) 1609 --- end) 1610 --- end 1611 --- ``` 1612 --- 1613 --- @type table<string,fun(command: lsp.Command, ctx: table)> 1614 lsp.commands = setmetatable({}, { 1615 __newindex = function(tbl, key, value) 1616 assert(type(key) == 'string', 'The key for commands in `vim.lsp.commands` must be a string') 1617 assert(type(value) == 'function', 'Command added to `vim.lsp.commands` must be a function') 1618 rawset(tbl, key, value) 1619 end, 1620 }) 1621 1622 return lsp