diff options
author | Lewis Russell <lewis6991@gmail.com> | 2024-02-27 15:20:32 +0000 |
---|---|---|
committer | Lewis Russell <me@lewisr.dev> | 2024-03-01 23:02:18 +0000 |
commit | a5fe8f59d98398d04bed8586cee73864bbcdde92 (patch) | |
tree | 9dd8086edc1e572ba1fddd03df17918dcd76a72e /runtime/lua/vim/lsp | |
parent | 813dd36b72979dfd05479eb6402b9becc0faea29 (diff) | |
download | rneovim-a5fe8f59d98398d04bed8586cee73864bbcdde92.tar.gz rneovim-a5fe8f59d98398d04bed8586cee73864bbcdde92.tar.bz2 rneovim-a5fe8f59d98398d04bed8586cee73864bbcdde92.zip |
docs: improve/add documentation of Lua types
- Added `@inlinedoc` so single use Lua types can be inlined into the
functions docs. E.g.
```lua
--- @class myopts
--- @inlinedoc
---
--- Documentation for some field
--- @field somefield integer
--- @param opts myOpts
function foo(opts)
end
```
Will be rendered as
```
foo(opts)
Parameters:
- {opts} (table) Object with the fields:
- somefield (integer) Documentation
for some field
```
- Marked many classes with with `@nodoc` or `(private)`.
We can eventually introduce these when we want to.
Diffstat (limited to 'runtime/lua/vim/lsp')
-rw-r--r-- | runtime/lua/vim/lsp/_changetracking.lua | 12 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 251 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 123 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/codelens.lua | 6 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/diagnostic.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/inlay_hint.lua | 24 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 40 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/semantic_tokens.lua | 26 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 91 |
10 files changed, 357 insertions, 219 deletions
diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua index 3ecdec1659..b2be53269f 100644 --- a/runtime/lua/vim/lsp/_changetracking.lua +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -61,7 +61,7 @@ local state_by_group = setmetatable({}, { end, }) ----@param client lsp.Client +---@param client vim.lsp.Client ---@return vim.lsp.CTGroup local function get_group(client) local allow_inc_sync = vim.F.if_nil(client.flags.allow_incremental_sync, true) --- @type boolean @@ -127,7 +127,7 @@ local function incremental_changes(state, encoding, bufnr, firstline, lastline, return incremental_change end ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr integer function M.init(client, bufnr) assert(client.offset_encoding, 'lsp client must have an offset_encoding') @@ -165,7 +165,7 @@ function M.init(client, bufnr) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client --- @param bufnr integer --- @param name string --- @return string @@ -189,7 +189,7 @@ local function reset_timer(buf_state) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client --- @param bufnr integer function M.reset_buf(client, bufnr) M.flush(client, bufnr) @@ -207,7 +207,7 @@ function M.reset_buf(client, bufnr) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client function M.reset(client) local state = state_by_group[get_group(client)] if not state then @@ -350,7 +350,7 @@ function M.send_changes(bufnr, firstline, lastline, new_lastline) end --- Flushes any outstanding change notification. ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr? integer function M.flush(client, bufnr) local group = get_group(client) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index d2e92de083..377c8680c7 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -11,7 +11,7 @@ local M = {} --- ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ----@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution| +---@param handler lsp.Handler? See |lsp-handler|. Follows |lsp-handler-resolution| --- ---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs ---for all successful requests. @@ -31,7 +31,7 @@ end --- Checks whether the language servers attached to the current buffer are --- ready. --- ----@return boolean if server responds. +---@return boolean : if server responds. ---@deprecated function M.server_ready() vim.deprecate('vim.lsp.buf.server_ready()', nil, '0.10') @@ -57,35 +57,57 @@ local function request_with_options(name, params, options) request(name, params, req_handler) end ---- Jumps to the declaration of the symbol under the cursor. ----@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. +--- @class vim.lsp.ListOpts +--- +--- list-handler replacing the default handler. +--- Called for any non-empty result. +--- This table can be used with |setqflist()| or |setloclist()|. E.g.: +--- ```lua +--- local function on_list(options) +--- vim.fn.setqflist({}, ' ', options) +--- vim.cmd.cfirst() +--- end --- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- vim.lsp.buf.definition({ on_list = on_list }) +--- vim.lsp.buf.references(nil, { on_list = on_list }) +--- ``` +--- +--- If you prefer loclist do something like this: +--- ```lua +--- local function on_list(options) +--- vim.fn.setloclist(0, {}, ' ', options) +--- vim.cmd.lopen() +--- end +--- ``` +--- @field on_list? fun(t: vim.lsp.LocationOpts.OnList) + +--- @class vim.lsp.LocationOpts.OnList +--- @field items table[] Structured like |setqflist-what| +--- @field title? string Title for the list. +--- @field context? table `ctx` from |lsp-handler| + +--- @class vim.lsp.LocationOpts: vim.lsp.ListOpts +--- +--- Jump to existing window if buffer is already open. +--- @field reuse_win? boolean + +--- Jumps to the declaration of the symbol under the cursor. +--- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. +--- @param options? vim.lsp.LocationOpts function M.declaration(options) local params = util.make_position_params() request_with_options(ms.textDocument_declaration, params, options) end --- Jumps to the definition of the symbol under the cursor. ---- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.definition(options) local params = util.make_position_params() request_with_options(ms.textDocument_definition, params, options) end --- Jumps to the definition of the type of the symbol under the cursor. ---- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.type_definition(options) local params = util.make_position_params() request_with_options(ms.textDocument_typeDefinition, params, options) @@ -93,10 +115,7 @@ end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. ---- ----@param options table|nil additional options ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.implementation(options) local params = util.make_position_params() request_with_options(ms.textDocument_implementation, params, options) @@ -156,45 +175,55 @@ local function range_from_selection(bufnr, mode) } end +--- @class vim.lsp.buf.format.Opts +--- @inlinedoc +--- +--- Can be used to specify FormattingOptions. Some unspecified options will be +--- automatically derived from the current Nvim options. +--- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions +--- @field formatting_options? table +--- +--- Time in milliseconds to block for formatting requests. No effect if async=true. +--- (default: `1000`) +--- @field timeout_ms? integer +--- +--- Restrict formatting to the clients attached to the given buffer. +--- (default: current buffer) +--- @field bufnr? integer +--- +--- Predicate used to filter clients. Receives a client as argument and must +--- return a boolean. Clients matching the predicate are included. Example: +--- ```lua +--- -- Never request typescript-language-server for formatting +--- vim.lsp.buf.format { +--- filter = function(client) return client.name ~= "tsserver" end +--- } +--- ``` +--- @field filter? fun(client: vim.lsp.Client): boolean? +--- +--- If true the method won't block. +--- Editing the buffer while formatting asynchronous can lead to unexpected +--- changes. +--- (Default: false) +--- @field async? boolean +--- +--- Restrict formatting to the client with ID (client.id) matching this field. +--- @field id? integer +--- +--- Restrict formatting to the client with name (client.name) matching this field. +--- @field name? string +--- +--- Range to format. +--- Table must contain `start` and `end` keys with {row,col} tuples using +--- (1,0) indexing. +--- (Default: current selection in visual mode, `nil` in other modes, +--- formatting the full buffer) +--- @field range? {start:integer[],end:integer[]} + --- Formats a buffer using the attached (and optionally filtered) language --- server clients. --- ---- @param options table|nil Optional table which holds the following optional fields: ---- - formatting_options (table|nil): ---- Can be used to specify FormattingOptions. Some unspecified options will be ---- automatically derived from the current Nvim options. ---- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions ---- - timeout_ms (integer|nil, default 1000): ---- Time in milliseconds to block for formatting requests. No effect if async=true ---- - bufnr (number|nil): ---- Restrict formatting to the clients attached to the given buffer, defaults to the current ---- buffer (0). ---- ---- - filter (function|nil): ---- Predicate used to filter clients. Receives a client as argument and must return a ---- boolean. Clients matching the predicate are included. Example: ---- ```lua ---- -- Never request typescript-language-server for formatting ---- vim.lsp.buf.format { ---- filter = function(client) return client.name ~= "tsserver" end ---- } ---- ``` ---- ---- - async boolean|nil ---- If true the method won't block. Defaults to false. ---- Editing the buffer while formatting asynchronous can lead to unexpected ---- changes. ---- ---- - id (number|nil): ---- Restrict formatting to the client with ID (client.id) matching this field. ---- - name (string|nil): ---- Restrict formatting to the client with name (client.name) matching this field. ---- ---- - range (table|nil) Range to format. ---- Table must contain `start` and `end` keys with {row,col} tuples using ---- (1,0) indexing. ---- Defaults to current selection in visual mode ---- Defaults to `nil` in other modes, formatting the full buffer +--- @param options? vim.lsp.buf.format.Opts function M.format(options) options = options or {} local bufnr = options.bufnr or api.nvim_get_current_buf() @@ -229,8 +258,7 @@ function M.format(options) end if options.async then - local do_format - do_format = function(idx, client) + local function do_format(idx, client) if not client then return end @@ -256,17 +284,22 @@ function M.format(options) end end +--- @class vim.lsp.buf.rename.Opts +--- @inlinedoc +--- +--- Predicate used to filter clients. Receives a client as argument and +--- must return a boolean. Clients matching the predicate are included. +--- @field filter? fun(client: vim.lsp.Client): boolean? +--- +--- Restrict clients used for rename to ones where client.name matches +--- this field. +--- @field name? string + --- Renames all references to the symbol under the cursor. --- ---@param new_name string|nil If not provided, the user will be prompted for a new --- name using |vim.ui.input()|. ----@param options table|nil additional options ---- - filter (function|nil): ---- Predicate used to filter clients. Receives a client as argument and ---- must return a boolean. Clients matching the predicate are included. ---- - name (string|nil): ---- Restrict clients used for rename to ones where client.name matches ---- this field. +---@param options? vim.lsp.buf.rename.Opts Additional options: function M.rename(new_name, options) options = options or {} local bufnr = options.bufnr or api.nvim_get_current_buf() @@ -386,8 +419,7 @@ end --- ---@param context (table|nil) Context for the request ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +---@param options? vim.lsp.ListOpts function M.references(context, options) validate({ context = { context, 't', true } }) local params = util.make_position_params() @@ -398,14 +430,13 @@ function M.references(context, options) end --- Lists all symbols in the current buffer in the quickfix window. ---- ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +--- @param options? vim.lsp.ListOpts function M.document_symbol(options) local params = { textDocument = util.make_text_document_params() } request_with_options(ms.textDocument_documentSymbol, params, options) end +--- @param call_hierarchy_items lsp.CallHierarchyItem[]? local function pick_call_hierarchy_item(call_hierarchy_items) if not call_hierarchy_items then return @@ -425,8 +456,10 @@ local function pick_call_hierarchy_item(call_hierarchy_items) return choice end +--- @param method string local function call_hierarchy(method) local params = util.make_position_params() + --- @param result lsp.CallHierarchyItem[]? request(ms.textDocument_prepareCallHierarchy, params, function(err, result, ctx) if err then vim.notify(err.message, vim.log.levels.WARN) @@ -545,9 +578,8 @@ end --- call, the user is prompted to enter a string on the command line. An empty --- string means no filtering is done. --- ----@param query string|nil optional ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +--- @param query string? optional +--- @param options? vim.lsp.ListOpts function M.workspace_symbol(query, options) query = query or npcall(vim.fn.input, 'Query: ') if query == nil then @@ -582,16 +614,36 @@ function M.clear_references() util.buf_clear_references() end +---@nodoc ---@class vim.lsp.CodeActionResultEntry ---@field error? lsp.ResponseError ---@field result? (lsp.Command|lsp.CodeAction)[] ---@field ctx lsp.HandlerContext ----@class vim.lsp.buf.code_action.opts ----@field context? lsp.CodeActionContext ----@field filter? fun(x: lsp.CodeAction|lsp.Command):boolean ----@field apply? boolean ----@field range? {start: integer[], end: integer[]} +--- @class vim.lsp.buf.code_action.Opts +--- @inlinedoc +--- +--- Corresponds to `CodeActionContext` of the LSP specification: +--- - {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred from the current +--- position if not provided. +--- - {only}? (`table`) List of LSP `CodeActionKind`s used to filter the code actions. +--- Most language servers support values like `refactor` +--- or `quickfix`. +--- - {triggerKind}? (`integer`) The reason why code actions were requested. +--- @field context? lsp.CodeActionContext +--- +--- Predicate taking an `CodeAction` and returning a boolean. +--- @field filter? fun(x: lsp.CodeAction|lsp.Command):boolean +--- +--- When set to `true`, and there is just one remaining action +--- (after filtering), the action is applied without user query. +--- @field apply? boolean +--- +--- Range for which code actions should be requested. +--- If in visual mode this defaults to the active selection. +--- Table must contain `start` and `end` keys with {row,col} tuples +--- using mark-like indexing. See |api-indexing| +--- @field range? {start: integer[], end: integer[]} --- This is not public because the main extension point is --- vim.ui.select which can be overridden independently. @@ -602,7 +654,7 @@ end --- need to be able to link a `CodeAction|Command` to the right client for --- `codeAction/resolve` ---@param results table<integer, vim.lsp.CodeActionResultEntry> ----@param opts? vim.lsp.buf.code_action.opts +---@param opts? vim.lsp.buf.code_action.Opts local function on_code_action_results(results, opts) ---@param a lsp.Command|lsp.CodeAction local function action_filter(a) @@ -647,14 +699,15 @@ local function on_code_action_results(results, opts) end ---@param action lsp.Command|lsp.CodeAction - ---@param client lsp.Client + ---@param client vim.lsp.Client ---@param ctx lsp.HandlerContext local function apply_action(action, client, ctx) if action.edit then util.apply_workspace_edit(action.edit, client.offset_encoding) end - if action.command then - local command = type(action.command) == 'table' and action.command or action + local a_cmd = action.command + if a_cmd then + local command = type(a_cmd) == 'table' and a_cmd or action client:_exec_cmd(command, ctx) end end @@ -676,7 +729,6 @@ local function on_code_action_results(results, opts) -- command: string -- arguments?: any[] -- - ---@type lsp.Client local client = assert(vim.lsp.get_client_by_id(choice.ctx.client_id)) local action = choice.action local bufnr = assert(choice.ctx.bufnr, 'Must have buffer number') @@ -726,29 +778,7 @@ end --- Selects a code action available at the current --- cursor position. --- ----@param options table|nil Optional table which holds the following optional fields: ---- - context: (table|nil) ---- Corresponds to `CodeActionContext` of the LSP specification: ---- - diagnostics (table|nil): ---- LSP `Diagnostic[]`. Inferred from the current ---- position if not provided. ---- - only (table|nil): ---- List of LSP `CodeActionKind`s used to filter the code actions. ---- Most language servers support values like `refactor` ---- or `quickfix`. ---- - triggerKind (number|nil): The reason why code actions were requested. ---- - filter: (function|nil) ---- Predicate taking an `CodeAction` and returning a boolean. ---- - apply: (boolean|nil) ---- When set to `true`, and there is just one remaining action ---- (after filtering), the action is applied without user query. ---- ---- - range: (table|nil) ---- Range for which code actions should be requested. ---- If in visual mode this defaults to the active selection. ---- Table must contain `start` and `end` keys with {row,col} tuples ---- using mark-like indexing. See |api-indexing| ---- +---@param options? vim.lsp.buf.code_action.Opts ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction ---@see vim.lsp.protocol.CodeActionTriggerKind function M.code_action(options) @@ -814,9 +844,8 @@ function M.code_action(options) end --- Executes an LSP server command. ---- ----@param command_params table A valid `ExecuteCommandParams` object ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand +--- @param command_params lsp.ExecuteCommandParams +--- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand function M.execute_command(command_params) validate({ command = { command_params.command, 's' }, diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index c1b41a7183..fcbaadbc57 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -6,38 +6,125 @@ local ms = lsp.protocol.Methods local changetracking = lsp._changetracking local validate = vim.validate ---- @alias vim.lsp.client.on_init_cb fun(client: lsp.Client, initialize_result: lsp.InitializeResult) ---- @alias vim.lsp.client.on_attach_cb fun(client: lsp.Client, bufnr: integer) +--- @alias vim.lsp.client.on_init_cb fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult) +--- @alias vim.lsp.client.on_attach_cb fun(client: vim.lsp.Client, bufnr: integer) --- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer) ---- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: lsp.ClientConfig) - ---- @class lsp.ClientConfig +--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) + +--- @class vim.lsp.ClientConfig +--- command string[] that launches the language +--- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like +--- "~" are not expanded), or function that creates an RPC client. Function receives +--- a `dispatchers` table and returns a table with member functions `request`, `notify`, +--- `is_closing` and `terminate`. +--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. +--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| --- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient? +--- +--- Directory to launch the `cmd` process. Not related to `root_dir`. +--- (default: cwd) --- @field cmd_cwd? string +--- +--- Environment flags to pass to the LSP on spawn. +--- Must be specified using a table. +--- Non-string values are coerced to string. +--- Example: +--- ```lua +--- { PORT = 8080; HOST = "0.0.0.0"; } +--- ``` --- @field cmd_env? table +--- +--- Daemonize the server process so that it runs in a separate process group from Nvim. +--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave +--- behind orphaned server processes. +--- (default: true) --- @field detached? boolean +--- +--- List of workspace folders passed to the language server. +--- For backwards compatibility rootUri and rootPath will be derived from the first workspace +--- folder in this list. See `workspaceFolders` in the LSP spec. --- @field workspace_folders? lsp.WorkspaceFolder[] +--- +--- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|, +--- passed to the language server on initialization. Hint: use make_client_capabilities() and modify +--- its result. +--- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an +--- array. --- @field capabilities? lsp.ClientCapabilities +--- +--- Map of language server method names to |lsp-handler| --- @field handlers? table<string,function> +--- +--- Map with language server specific settings. These are returned to the language server if +--- requested via `workspace/configuration`. Keys are case-sensitive. --- @field settings? table +--- +--- Table that maps string of clientside commands to user-defined functions. +--- Commands passed to start_client take precedence over the global command registry. Each key +--- must be a unique command name, and the value is a function which is called if any LSP action +--- (code action, code lenses, ...) triggers the command. --- @field commands? table<string,fun(command: lsp.Command, ctx: table)> +--- +--- Values to pass in the initialization request as `initializationOptions`. See `initialize` in +--- the LSP spec. --- @field init_options? table +--- +--- Name in log messages. +--- (default: client-id) --- @field name? string +--- +--- Language ID as string. Defaults to the filetype. --- @field get_language_id? fun(bufnr: integer, filetype: string): string ---- @field offset_encoding? string +--- +--- The encoding that the LSP server expects. Client does not verify this is correct. +--- @field offset_encoding? 'utf-8'|'utf-16'|'utf-32' +--- +--- Callback invoked when the client operation throws an error. `code` is a number describing the error. +--- Other arguments may be passed depending on the error kind. See `vim.lsp.rpc.client_errors` +--- for possible errors. Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name. --- @field on_error? fun(code: integer, err: string) +--- +--- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters +--- being sent to the server and `config` is the config that was passed to |vim.lsp.start_client()|. +--- You can use this to modify parameters before they are sent. --- @field before_init? vim.lsp.client.before_init_cb +--- +--- Callback invoked after LSP "initialize", where `result` is a table of `capabilities` +--- and anything else the server may send. For example, clangd sends +--- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was sent to it. +--- You can only modify the `client.offset_encoding` here before any notifications are sent. --- @field on_init? elem_or_list<vim.lsp.client.on_init_cb> +--- +--- Callback invoked on client exit. +--- - code: exit code of the process +--- - signal: number describing the signal used to terminate (if any) +--- - client_id: client handle --- @field on_exit? elem_or_list<vim.lsp.client.on_exit_cb> +--- +--- Callback invoked when client attaches to a buffer. --- @field on_attach? elem_or_list<vim.lsp.client.on_attach_cb> +--- +--- Passed directly to the language server in the initialize request. Invalid/empty values will +--- (default: "off") --- @field trace? 'off'|'messages'|'verbose' +--- +--- A table with flags for the client. The current (experimental) flags are: +--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits +--- - debounce_text_changes (number, default 150): Debounce didChange +--- notifications to the server by the given number in milliseconds. No debounce +--- occurs if nil +--- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to +--- exit cleanly after sending the "shutdown" request before sending kill -15. +--- If set to false, nvim exits immediately after sending the "shutdown" request to the server. --- @field flags? table +--- +--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization. --- @field root_dir? string ---- @class lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> +--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> --- @field pending table<lsp.ProgressToken,lsp.LSPAny> ---- @class lsp.Client +--- @class vim.lsp.Client --- --- The id allocated to the client. --- @field id integer @@ -67,7 +154,7 @@ local validate = vim.validate --- --- copy of the table that was passed by the user --- to |vim.lsp.start_client()|. ---- @field config lsp.ClientConfig +--- @field config vim.lsp.ClientConfig --- --- Response from the server sent on --- initialize` describing the server's capabilities. @@ -75,7 +162,7 @@ local validate = vim.validate --- --- A ring buffer (|vim.ringbuf()|) containing progress messages --- sent by the server. ---- @field progress lsp.Client.Progress +--- @field progress vim.lsp.Client.Progress --- --- @field initialized true? --- @@ -239,7 +326,7 @@ local function default_get_language_id(_bufnr, filetype) end --- Validates a client configuration as given to |vim.lsp.start_client()|. ---- @param config lsp.ClientConfig +--- @param config vim.lsp.ClientConfig local function validate_config(config) validate({ config = { config, 't' }, @@ -285,7 +372,7 @@ local function get_trace(trace) end --- @param id integer ---- @param config lsp.ClientConfig +--- @param config vim.lsp.ClientConfig --- @return string local function get_name(id, config) local name = config.name @@ -328,8 +415,8 @@ local function ensure_list(x) end --- @package ---- @param config lsp.ClientConfig ---- @return lsp.Client? +--- @param config vim.lsp.ClientConfig +--- @return vim.lsp.Client? function Client.create(config) validate_config(config) @@ -337,7 +424,7 @@ function Client.create(config) local id = client_index local name = get_name(id, config) - --- @class lsp.Client + --- @class vim.lsp.Client local self = { id = id, config = config, @@ -370,7 +457,7 @@ function Client.create(config) --- - lsp.WorkDoneProgressBegin, --- - lsp.WorkDoneProgressReport (extended with title from Begin) --- - lsp.WorkDoneProgressEnd (extended with title from Begin) - progress = vim.ringbuf(50) --[[@as lsp.Client.Progress]], + progress = vim.ringbuf(50) --[[@as vim.lsp.Client.Progress]], --- @deprecated use client.progress instead messages = { name = name, messages = {}, progress = {}, status = {} }, @@ -421,6 +508,7 @@ function Client.create(config) return self end +--- @private --- @param cbs function[] --- @param error_id integer --- @param ... any @@ -698,7 +786,7 @@ function Client:_cancel_request(id) return self.rpc.notify(ms.dollar_cancelRequest, { id = id }) end ---- @nodoc +--- @private --- Stops a client, optionally with force. --- --- By default, it will just ask the - server to shutdown without force. If @@ -853,6 +941,7 @@ function Client:write_error(code, err) err_message(self._log_prefix, ': Error ', client_error, ': ', vim.inspect(err)) end +--- @private --- @param method string --- @param opts? {bufnr: integer?} function Client:_supports_method(method, opts) diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 7aed6f99e3..48c096c0c1 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -279,7 +279,8 @@ function M.on_codelens(err, result, ctx, _) end) end ---- @class vim.lsp.codelens.RefreshOptions +--- @class vim.lsp.codelens.refresh.Opts +--- @inlinedoc --- @field bufnr integer? filter by buffer. All buffers if nil, 0 for current buffer --- Refresh the lenses. @@ -292,8 +293,7 @@ end --- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh({ bufnr = 0 }) --- ``` --- ---- @param opts? vim.lsp.codelens.RefreshOptions Table with the following fields: ---- - `bufnr` (integer|nil): filter by buffer. All buffers if nil, 0 for current buffer +--- @param opts? vim.lsp.codelens.refresh.Opts Optional fields function M.refresh(opts) opts = opts or {} local bufnr = opts.bufnr and resolve_bufnr(opts.bufnr) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 1fa67fc473..6156821093 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -390,7 +390,7 @@ local function clear(bufnr) end end ----@class lsp.diagnostic.bufstate +---@class (private) lsp.diagnostic.bufstate ---@field enabled boolean Whether inlay hints are enabled for this buffer ---@type table<integer, lsp.diagnostic.bufstate> local bufstates = {} diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 781d720486..d816fb1482 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -412,6 +412,7 @@ M[ms.textDocument_hover] = M.hover ---@param _ nil not used ---@param result (table) result of LSP method; a location or a list of locations. ---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method +---@param config? vim.lsp.buf.LocationOpts ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 49dc35fdf6..ec676ea97f 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -4,12 +4,12 @@ local ms = require('vim.lsp.protocol').Methods local api = vim.api local M = {} ----@class lsp.inlay_hint.bufstate +---@class (private) vim.lsp.inlay_hint.bufstate ---@field version? integer ---@field client_hints? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints) ---@field applied table<integer, integer> Last version of hints applied to this line ---@field enabled boolean Whether inlay hints are enabled for this buffer ----@type table<integer, lsp.inlay_hint.bufstate> +---@type table<integer, vim.lsp.inlay_hint.bufstate> local bufstates = {} local namespace = api.nvim_create_namespace('vim_lsp_inlayhint') @@ -103,11 +103,14 @@ function M.on_refresh(err, _, ctx, _) return vim.NIL end ---- @class vim.lsp.inlay_hint.get.filter +--- Optional filters |kwargs|: +--- @class vim.lsp.inlay_hint.get.Filter +--- @inlinedoc --- @field bufnr integer? --- @field range lsp.Range? ---- + --- @class vim.lsp.inlay_hint.get.ret +--- @inlinedoc --- @field bufnr integer --- @field client_id integer --- @field inlay_hint lsp.InlayHint @@ -130,17 +133,8 @@ end --- }) --- ``` --- ---- @param filter vim.lsp.inlay_hint.get.filter? ---- Optional filters |kwargs|: ---- - bufnr (integer?): 0 for current buffer ---- - range (lsp.Range?) ---- +--- @param filter vim.lsp.inlay_hint.get.Filter? --- @return vim.lsp.inlay_hint.get.ret[] ---- Each list item is a table with the following fields: ---- - bufnr (integer) ---- - client_id (integer) ---- - inlay_hint (lsp.InlayHint) ---- --- @since 12 function M.get(filter) vim.validate({ filter = { filter, 'table', true } }) @@ -241,7 +235,7 @@ end --- Refresh inlay hints, only if we have attached clients that support it ---@param bufnr (integer) Buffer handle, or 0 for current ----@param opts? lsp.util.RefreshOptions Additional options to pass to util._refresh +---@param opts? vim.lsp.util._refresh.Opts Additional options to pass to util._refresh ---@private local function _refresh(bufnr, opts) opts = opts or {} diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index e52c06a1bd..8e014b1063 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -26,7 +26,7 @@ local function format_message_with_content_length(message) }) end ----@class vim.lsp.rpc.Headers: {string: any} +---@class (private) vim.lsp.rpc.Headers: {string: any} ---@field content_length integer --- Parses an LSP Message's header @@ -193,7 +193,9 @@ function M.rpc_response_error(code, message, data) }) end +--- Dispatchers for LSP message types. --- @class vim.lsp.rpc.Dispatchers +--- @inlinedoc --- @field notification fun(method: string, params: table) --- @field server_request fun(method: string, params: table): any?, lsp.ResponseError? --- @field on_exit fun(code: integer, signal: integer) @@ -266,8 +268,7 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error) end end ----@private ----@class vim.lsp.rpc.Client +---@class (private) vim.lsp.rpc.Client ---@field message_index integer ---@field message_callbacks table<integer, function> dict of message_id to callback ---@field notify_reply_callbacks table<integer, function> dict of message_id to callback @@ -522,7 +523,7 @@ function Client:handle_body(body) end end ----@class vim.lsp.rpc.Transport +---@class (private) vim.lsp.rpc.Transport ---@field write fun(msg: string) ---@field is_closing fun(): boolean ---@field terminate fun() @@ -721,32 +722,21 @@ function M.domain_socket_connect(pipe_path) end end ----@class vim.lsp.rpc.ExtraSpawnParams ----@field cwd? string Working directory for the LSP server process ----@field detached? boolean Detach the LSP server process from the current process ----@field env? table<string,string> Additional environment variables for LSP server process. See |vim.system| +--- Additional context for the LSP server process. +--- @class vim.lsp.rpc.ExtraSpawnParams +--- @inlinedoc +--- @field cwd? string Working directory for the LSP server process +--- @field detached? boolean Detach the LSP server process from the current process +--- @field env? table<string,string> Additional environment variables for LSP server process. See |vim.system()| --- Starts an LSP server process and create an LSP RPC client object to --- interact with it. Communication with the spawned process happens via stdio. For --- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()| --- ----@param cmd string[] Command to start the LSP server. ---- ----@param dispatchers? vim.lsp.rpc.Dispatchers Dispatchers for LSP message types. ---- Valid dispatcher names are: ---- - `"notification"` ---- - `"server_request"` ---- - `"on_error"` ---- - `"on_exit"` ---- ----@param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams Additional context for the LSP ---- server process. May contain: ---- - {cwd} (string) Working directory for the LSP server process ---- - {detached?} (boolean) Detach the LSP server process from the current process. ---- Defaults to false on Windows and true otherwise. ---- - {env?} (table) Additional environment variables for LSP server process ---- ----@return vim.lsp.rpc.PublicClient? Client RPC object, with these methods: +--- @param cmd string[] Command to start the LSP server. +--- @param dispatchers? vim.lsp.rpc.Dispatchers +--- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams +--- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods: --- - `notify()` |vim.lsp.rpc.notify()| --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index fe8638bdfa..92546e8520 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -4,7 +4,7 @@ local ms = require('vim.lsp.protocol').Methods local util = require('vim.lsp.util') local uv = vim.uv ---- @class STTokenRange +--- @class (private) STTokenRange --- @field line integer line number 0-based --- @field start_col integer start column 0-based --- @field end_col integer end column 0-based @@ -12,23 +12,23 @@ local uv = vim.uv --- @field modifiers table<string,boolean> token modifiers as a set. E.g., { static = true, readonly = true } --- @field marked boolean whether this token has had extmarks applied --- ---- @class STCurrentResult +--- @class (private) STCurrentResult --- @field version? integer document version associated with this result --- @field result_id? string resultId from the server; used with delta requests --- @field highlights? STTokenRange[] cache of highlight ranges for this document version --- @field tokens? integer[] raw token array as received by the server. used for calculating delta responses --- @field namespace_cleared? boolean whether the namespace was cleared for this result yet --- ---- @class STActiveRequest +--- @class (private) STActiveRequest --- @field request_id? integer the LSP request ID of the most recent request sent to the server --- @field version? integer the document version associated with the most recent request --- ---- @class STClientState +--- @class (private) STClientState --- @field namespace integer --- @field active_request STActiveRequest --- @field current_result STCurrentResult ----@class STHighlighter +---@class (private) STHighlighter ---@field active table<integer, STHighlighter> ---@field bufnr integer ---@field augroup integer augroup for buffer events @@ -92,7 +92,7 @@ end --- ---@param data integer[] ---@param bufnr integer ----@param client lsp.Client +---@param client vim.lsp.Client ---@param request STActiveRequest ---@return STTokenRange[] local function tokens_to_ranges(data, bufnr, client, request) @@ -646,6 +646,7 @@ function M.stop(bufnr, client_id) end end +--- @nodoc --- @class STTokenRangeInspect : STTokenRange --- @field client_id integer @@ -727,6 +728,13 @@ function M.force_refresh(bufnr) end end +--- @class vim.lsp.semantic_tokens.highlight_token.Opts +--- @inlinedoc +--- +--- Priority for the applied extmark. +--- (Default: `vim.highlight.priorities.semantic_tokens + 3`) +--- @field priority? integer + --- Highlight a semantic token. --- --- Apply an extmark with a given highlight group for a semantic token. The @@ -735,11 +743,9 @@ end --- use inside |LspTokenUpdate| callbacks. ---@param token (table) a semantic token, found as `args.data.token` in |LspTokenUpdate|. ---@param bufnr (integer) the buffer to highlight ----@param client_id (integer) The ID of the |vim.lsp.client| +---@param client_id (integer) The ID of the |vim.lsp.Client| ---@param hl_group (string) Highlight group name ----@param opts (table|nil) Optional parameters. ---- - priority: (integer|nil) Priority for the applied extmark. Defaults ---- to `vim.highlight.priorities.semantic_tokens + 3` +---@param opts? vim.lsp.semantic_tokens.highlight_token.Opts Optional parameters: function M.highlight_token(token, bufnr, client_id, hl_group, opts) local highlighter = STHighlighter.active[bufnr] if not highlighter then diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 0553d39851..60d0f0cc83 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -675,13 +675,15 @@ local function get_bufs_with_prefix(prefix) return buffers end +--- @class vim.lsp.util.rename.Opts +--- @inlinedoc +--- @field overwrite? boolean +--- @field ignoreIfExists? boolean + --- Rename old_fname to new_fname ---- ----@param old_fname string ----@param new_fname string ----@param opts? table options ---- - overwrite? boolean ---- - ignoreIfExists? boolean +--- @param old_fname string +--- @param new_fname string +--- @param opts? vim.lsp.util.rename.Opts Options: function M.rename(old_fname, new_fname, opts) opts = opts or {} local skip = not opts.overwrite or opts.ignoreIfExists @@ -1450,7 +1452,7 @@ function M.stylize_markdown(bufnr, contents, opts) return stripped end ---- @class lsp.util.NormalizeMarkdownOptions +--- @class (private) vim.lsp.util._normalize_markdown.Opts --- @field width integer Thematic breaks are expanded to this size. Defaults to 80. --- Normalizes Markdown input to a canonical form. @@ -1466,7 +1468,7 @@ end --- ---@private ---@param contents string[] ----@param opts? lsp.util.NormalizeMarkdownOptions +---@param opts? vim.lsp.util._normalize_markdown.Opts ---@return string[] table of lines containing normalized Markdown ---@see https://github.github.com/gfm function M._normalize_markdown(contents, opts) @@ -1537,7 +1539,7 @@ local function close_preview_autocmd(events, winnr, bufnrs) end end ----@internal +---@private --- Computes size of float needed to show contents (with optional wrapping) --- ---@param contents table of lines to show in window @@ -1613,24 +1615,50 @@ function M._make_floating_popup_size(contents, opts) return width, height end +--- @class vim.lsp.util.open_floating_preview.Opts +--- @inlinedoc +--- +--- Height of floating window +--- @field height? integer +--- +--- Width of floating window +--- @field width? integer +--- +--- Wrap long lines +--- (default: `true`) +--- @field wrap? boolean +--- +--- Character to wrap at for computing height when wrap is enabled +--- @field wrap_at? integer +--- +--- Maximal width of floating window +--- @field max_width? integer +--- +--- Maximal height of floating window +--- @field max_height? integer +--- +--- If a popup with this id is opened, then focus it +--- @field focus_id? string +--- +--- List of events that closes the floating window +--- @field close_events? table +--- +--- Make float focusable. +--- (default: `true`) +--- @field focusable? boolean +--- +--- If `true`, and if {focusable} is also `true`, focus an existing floating +--- window with the same {focus_id} +--- (default: `true`) +--- @field focus? boolean + --- Shows contents in a floating window. --- ---@param contents table of lines to show in window ---@param syntax string of syntax to set for opened buffer ----@param opts table with optional fields (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| ---- before they are passed on to |nvim_open_win()|) ---- - height: (integer) height of floating window ---- - width: (integer) width of floating window ---- - wrap: (boolean, default true) wrap long lines ---- - wrap_at: (integer) character to wrap at for computing height when wrap is enabled ---- - max_width: (integer) maximal width of floating window ---- - max_height: (integer) maximal height of floating window ---- - focus_id: (string) if a popup with this id is opened, then focus it ---- - close_events: (table) list of events that closes the floating window ---- - focusable: (boolean, default true) Make float focusable ---- - focus: (boolean, default true) If `true`, and if {focusable} ---- is also `true`, focus an existing floating window with the same ---- {focus_id} +---@param opts? vim.lsp.util.open_floating_preview.Opts with optional fields +--- (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| +--- before they are passed on to |nvim_open_win()|) ---@return integer bufnr of newly created float window ---@return integer winid of newly created float window preview window function M.open_floating_preview(contents, syntax, opts) @@ -1794,7 +1822,8 @@ local position_sort = sort_by_key(function(v) return { v.start.line, v.start.character } end) ----@class vim.lsp.util.LocationItem +---@class vim.lsp.util.locations_to_items.ret +---@inlinedoc ---@field filename string ---@field lnum integer 1-indexed line number ---@field col integer 1-indexed column @@ -1813,7 +1842,7 @@ end) ---@param locations lsp.Location[]|lsp.LocationLink[] ---@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32 --- default to first client of buffer ----@return vim.lsp.util.LocationItem[] list of items +---@return vim.lsp.util.locations_to_items.ret[] function M.locations_to_items(locations, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -2221,16 +2250,16 @@ local function make_line_range_params(bufnr, start_line, end_line, offset_encodi } end ----@private ---- Request updated LSP information for a buffer. ---- ----@class lsp.util.RefreshOptions +---@class (private) vim.lsp.util._refresh.Opts ---@field bufnr integer? Buffer to refresh (default: 0) ---@field only_visible? boolean Whether to only refresh for the visible regions of the buffer (default: false) ---@field client_id? integer Client ID to refresh (default: all clients) --- + +---@private +--- Request updated LSP information for a buffer. +--- ---@param method string LSP method to call ----@param opts? lsp.util.RefreshOptions Options table +---@param opts? vim.lsp.util._refresh.Opts Options table function M._refresh(method, opts) opts = opts or {} local bufnr = opts.bufnr |