neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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