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.
This commit is contained in:
Lewis Russell 2024-02-27 15:20:32 +00:00 committed by Lewis Russell
parent 813dd36b72
commit a5fe8f59d9
47 changed files with 2014 additions and 1450 deletions

View File

@ -141,7 +141,7 @@ LSP FUNCTIONS
- *vim.lsp.buf.range_formatting()* Use |vim.lsp.formatexpr()|
or |vim.lsp.buf.format()| instead.
- *vim.lsp.util.get_progress_messages()* Use |vim.lsp.status()| or access
`progress` of |vim.lsp.client|
`progress` of |vim.lsp.Client|
- *vim.lsp.get_active_clients()* Use |vim.lsp.get_clients()|
- *vim.lsp.for_each_buffer_client()* Use |vim.lsp.get_clients()|
- *vim.lsp.util.lookup_section()* Use |vim.tbl_get()| and

View File

@ -179,6 +179,8 @@ Strict "vimdoc" subset:
- Do not use indentation in random places—that prevents the page from using
"flow" layout. If you need a preformatted section, put it in
a |help-codeblock| starting with ">".
- Parameters and fields are documented as `{foo}`.
- Optional parameters and fields are documented as `{foo}?`.
C docstrings ~
@ -189,9 +191,8 @@ from the docstrings defined in src/nvim/api/*.c.
Docstring format:
- Lines start with `///`
- Special tokens start with `@` followed by the token name:
`@note`, `@param`, `@returns`
- Limited markdown is supported.
- List-items start with `-` (useful to nest or "indent")
`@note`, `@param`, `@return`
- Markdown is supported.
- Use ``` for code samples.
Code samples can be annotated as `vim` or `lua`
@ -233,11 +234,33 @@ definitions. The |lua-vim| :help is generated from the docstrings.
Docstring format:
- Use LuaCATS annotations: https://luals.github.io/wiki/annotations/
- Limited markdown is supported.
- List-items start with `-` (useful to nest or "indent")
- Markdown is supported.
- Use ``` for code samples.
Code samples can be annotated as `vim` or `lua`
- Use `@nodoc` to prevent documentation generation.
- Use `@inlinedoc` to inline `@class` blocks into `@param` blocks.
E.g. >lua
--- Object with fields:
--- @class myOpts
--- @inlinedoc
---
--- Documentation for some field
--- @field somefield? integer
--- @param opts? myOpts
function foo(opts)
end
<
Will be rendered as: >vimdoc
foo({opts})
Parameters:
- {opts}? (table) Object with the fields:
- {somefield}? (integer) Documentation
for some field
<
- Files which has `@meta` are only used for typing and documentation.
Example: the help for |vim.paste()| is generated from a docstring decorating

View File

@ -38,24 +38,6 @@ optionally supplied). A good rule of thumb is that if a method is meant to
modify the diagnostics for a buffer (e.g. |vim.diagnostic.set()|) then it
requires a namespace.
*diagnostic-structure*
A diagnostic is a Lua table with the following keys. Required keys are
indicated with (+):
bufnr: Buffer number
lnum(+): The starting line of the diagnostic
end_lnum: The final line of the diagnostic
col(+): The starting column of the diagnostic
end_col: The final column of the diagnostic
severity: The severity of the diagnostic |vim.diagnostic.severity|
message(+): The diagnostic text
source: The source of the diagnostic
code: The diagnostic code
user_data: Arbitrary data plugins or users can add
Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based
rows and columns). |api-indexing|
*vim.diagnostic.severity* *diagnostic-severity*
The "severity" key in a diagnostic is one of the values defined in
`vim.diagnostic.severity`:
@ -361,6 +343,105 @@ Example: >lua
==============================================================================
Lua module: vim.diagnostic *diagnostic-api*
*vim.Diagnostic*
*diagnostic-structure*
Diagnostics use the same indexing as the rest of the Nvim API (i.e.
0-based rows and columns). |api-indexing|
Fields: ~
• {bufnr}? (`integer`) Buffer number
• {lnum} (`integer`) The starting line of the diagnostic
(0-indexed)
• {end_lnum}? (`integer`) The final line of the diagnostic (0-indexed)
• {col} (`integer`) The starting column of the diagnostic
(0-indexed)
• {end_col}? (`integer`) The final column of the diagnostic
(0-indexed)
• {severity}? (`vim.diagnostic.Severity`) The severity of the
diagnostic |vim.diagnostic.severity|
• {message} (`string`) The diagnostic text
• {source}? (`string`) The source of the diagnostic
• {code}? (`string|integer`) The diagnostic code
• {_tags}? (`{ deprecated: boolean, unnecessary: boolean}`)
• {user_data}? (`any`) arbitrary data plugins can add
• {namespace}? (`integer`)
*vim.diagnostic.NS*
Fields: ~
• {name} (`string`)
• {opts} (`vim.diagnostic.Opts`)
• {user_data} (`table`)
• {disabled}? (`boolean`)
*vim.diagnostic.Opts*
Fields: ~
• {float}? (`boolean|vim.diagnostic.Opts.Float`)
• {update_in_insert}? (`boolean`)
• {underline}? (`boolean|vim.diagnostic.Opts.Underline`)
• {virtual_text}? (`boolean|vim.diagnostic.Opts.VirtualText`)
• {signs}? (`boolean|vim.diagnostic.Opts.Signs`)
• {severity_sort}? (`boolean|{reverse?:boolean}`)
*vim.diagnostic.Opts.Float*
Fields: ~
• {bufnr}? (`integer`)
• {namespace}? (`integer`)
• {scope}? (`'line'|'buffer'|'cursor'|'c'|'l'|'b'`)
• {pos}? (`integer|{[1]:integer,[2]:integer}`)
• {severity_sort}? (`boolean|{reverse?:boolean}`)
• {severity}? (`vim.diagnostic.SeverityFilter`)
• {header}? (`string|{[1]:string,[2]:any}`)
• {source}? (`boolean|string`)
• {format}? (`fun(diagnostic:vim.Diagnostic): string`)
• {prefix}? (`string|table`)
• {suffix}? (`string|table`)
• {focus_id}? (`string`)
*vim.diagnostic.Opts.Signs*
Fields: ~
• {severity}? (`vim.diagnostic.SeverityFilter`)
• {priority}? (`integer`)
• {text}? (`table<vim.diagnostic.Severity,string>`)
• {numhl}? (`table<vim.diagnostic.Severity,string>`)
• {linehl}? (`table<vim.diagnostic.Severity,string>`)
• {texthl}? (`table<vim.diagnostic.Severity,string>`)
*vim.diagnostic.Opts.Underline*
Fields: ~
• {severity}? (`vim.diagnostic.SeverityFilter`)
*vim.diagnostic.Opts.VirtualText*
Fields: ~
• {severity}? (`vim.diagnostic.SeverityFilter`)
• {source}? (`boolean|string`)
• {prefix}? (`string|function`)
• {suffix}? (`string|function`)
• {spacing}? (`integer`)
• {format}? (`function`)
• {hl_mode}? (`'replace'|'combine'|'blend'`)
• {virt_text}? (`{[1]:string,[2]:any}[]`)
• {virt_text_pos}? (`'eol'|'overlay'|'right_align'|'inline'`)
• {virt_text_win_col}? (`integer`)
• {virt_text_hide}? (`boolean`)
*vim.diagnostic.OptsResolved*
Fields: ~
• {float} (`vim.diagnostic.Opts.Float`)
• {update_in_insert} (`boolean`)
• {underline} (`vim.diagnostic.Opts.Underline`)
• {virtual_text} (`vim.diagnostic.Opts.VirtualText`)
• {signs} (`vim.diagnostic.Opts.Signs`)
• {severity_sort} (`{reverse?:boolean}`)
config({opts}, {namespace}) *vim.diagnostic.config()*
Configure diagnostic options globally or for a specific diagnostic
namespace.
@ -518,7 +599,8 @@ fromqflist({list}) *vim.diagnostic.fromqflist()*
|getloclist()|.
Return: ~
(`vim.Diagnostic[]`) array of |diagnostic-structure|
(`vim.Diagnostic[]`) array of |diagnostic-structure|. See
|vim.Diagnostic|.
get({bufnr}, {opts}) *vim.diagnostic.get()*
Get current diagnostics.
@ -538,7 +620,7 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
Return: ~
(`vim.Diagnostic[]`) table A list of diagnostic items
|diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and
`severity` are guaranteed to be present.
`severity` are guaranteed to be present. See |vim.Diagnostic|.
get_namespace({namespace}) *vim.diagnostic.get_namespace()*
Get namespace metadata.
@ -563,7 +645,7 @@ get_next({opts}) *vim.diagnostic.get_next()*
• {opts} (`table?`) See |vim.diagnostic.goto_next()|
Return: ~
(`vim.Diagnostic?`) Next diagnostic
(`vim.Diagnostic?`) Next diagnostic. See |vim.Diagnostic|.
get_next_pos({opts}) *vim.diagnostic.get_next_pos()*
Return the position of the next diagnostic in the current buffer.
@ -582,7 +664,7 @@ get_prev({opts}) *vim.diagnostic.get_prev()*
• {opts} (`table?`) See |vim.diagnostic.goto_next()|
Return: ~
(`vim.Diagnostic?`) Previous diagnostic
(`vim.Diagnostic?`) Previous diagnostic. See |vim.Diagnostic|.
get_prev_pos({opts}) *vim.diagnostic.get_prev_pos()*
Return the position of the previous diagnostic in the current buffer.
@ -599,21 +681,22 @@ goto_next({opts}) *vim.diagnostic.goto_next()*
Parameters: ~
• {opts} (`table?`) Configuration table with the following keys:
namespace: (integer) Only consider diagnostics from the
{namespace} (`integer`) Only consider diagnostics from the
given namespace.
• cursor_position: (cursor position) Cursor position as a
(row, col) tuple. See |nvim_win_get_cursor()|. Defaults to
the current cursor position.
• wrap: (boolean, default true) Whether to loop around file or
not. Similar to 'wrapscan'.
• severity: See |diagnostic-severity|.
• float: (boolean or table, default true) If "true", call
|vim.diagnostic.open_float()| after moving. If a table, pass
the table as the {opts} parameter to
|vim.diagnostic.open_float()|. Unless overridden, the float
will show diagnostics at the new cursor position (as if
"cursor" were passed to the "scope" option).
• win_id: (number, default 0) Window ID
• {cursor_position}? (`{[1]:integer,[2]:integer}`) Cursor
position as a (row, col) tuple. See |nvim_win_get_cursor()|.
Defaults to the current cursor position.
• {wrap}? (`boolean`, default: `true`) Whether to loop around
file or not. Similar to 'wrapscan'.
• {severity} (`vim.diagnostic.Severity`) See
|diagnostic-severity|.
• {float}? (`boolean|vim.diagnostic.Opts.Float`, default:
`true`) If "true", call |vim.diagnostic.open_float()| after
moving. If a table, pass the table as the {opts} parameter
to |vim.diagnostic.open_float()|. Unless overridden, the
float will show diagnostics at the new cursor position (as
if "cursor" were passed to the "scope" option).
• {win_id}? (`integer`, default: `0`) Window ID
goto_prev({opts}) *vim.diagnostic.goto_prev()*
Move to the previous diagnostic in the current buffer.
@ -678,7 +761,7 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
Return: ~
(`vim.Diagnostic?`) |diagnostic-structure| or `nil` if {pat} fails to
match {str}.
match {str}. See |vim.Diagnostic|.
open_float({opts}) *vim.diagnostic.open_float()*
Show diagnostics in a floating window.
@ -758,7 +841,7 @@ set({namespace}, {bufnr}, {diagnostics}, {opts}) *vim.diagnostic.set()*
• {namespace} (`integer`) The diagnostic namespace
• {bufnr} (`integer`) Buffer number
• {diagnostics} (`vim.Diagnostic[]`) A list of diagnostic items
|diagnostic-structure|
|diagnostic-structure|. See |vim.Diagnostic|.
• {opts} (`table?`) Display options to pass to
|vim.diagnostic.show()|
@ -767,28 +850,30 @@ setloclist({opts}) *vim.diagnostic.setloclist()*
Parameters: ~
• {opts} (`table?`) Configuration table with the following keys:
namespace: (number) Only add diagnostics from the given
{namespace}? (`integer`) Only add diagnostics from the given
namespace.
winnr: (number, default 0) Window number to set location
list for.
open: (boolean, default true) Open the location list after
setting.
title: (string) Title of the location list. Defaults to
{winnr}? (`integer`, default: `0`) Window number to set
location list for.
{open}? (`boolean`, default: `true`) Open the location list
after setting.
{title}? (`string`) Title of the location list. Defaults to
"Diagnostics".
• severity: See |diagnostic-severity|.
• {severity}? (`vim.diagnostic.Severity`) See
|diagnostic-severity|.
setqflist({opts}) *vim.diagnostic.setqflist()*
Add all diagnostics to the quickfix list.
Parameters: ~
• {opts} (`table?`) Configuration table with the following keys:
namespace: (number) Only add diagnostics from the given
{namespace}? (`integer`) Only add diagnostics from the given
namespace.
open: (boolean, default true) Open quickfix list after
setting.
title: (string) Title of quickfix list. Defaults to
{open}? (`boolean`, default: `true`) Open quickfix list
after setting.
{title}? (`string`) Title of quickfix list. Defaults to
"Diagnostics".
• severity: See |diagnostic-severity|.
• {severity}? (`vim.diagnostic.Severity`) See
|diagnostic-severity|.
*vim.diagnostic.show()*
show({namespace}, {bufnr}, {diagnostics}, {opts})
@ -804,7 +889,7 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
namespace and buffer. This can be used to display a
list of diagnostics without saving them or to display
only a subset of diagnostics. May not be used when
{namespace} or {bufnr} is nil.
{namespace} or {bufnr} is nil. See |vim.Diagnostic|.
• {opts} (`table?`) Display options. See
|vim.diagnostic.config()|.
@ -814,7 +899,7 @@ toqflist({diagnostics}) *vim.diagnostic.toqflist()*
Parameters: ~
• {diagnostics} (`vim.Diagnostic[]`) List of diagnostics
|diagnostic-structure|.
|diagnostic-structure|. See |vim.Diagnostic|.
Return: ~
(`table[]`) of quickfix list items |setqflist-what|

View File

@ -218,7 +218,7 @@ Each response handler has this signature: >
- {ctx} (table) Table of calling state associated with the
handler, with these keys:
- {method} (string) |lsp-method| name.
- {client_id} (number) |vim.lsp.client| identifier.
- {client_id} (number) |vim.lsp.Client| identifier.
- {bufnr} (Buffer) Buffer handle.
- {params} (table|nil) Request parameters table.
- {version} (number) Document version at time of
@ -366,31 +366,6 @@ https://microsoft.github.io/language-server-protocol/specifications/specificatio
LSP notification shape:
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#notificationMessage
*lsp-on-list-handler*
`on_list` receives a table with:
- `items` table[], structured like |setqflist-what|
- `title` string, title for the list.
- `context` table|nil. `ctx` from |lsp-handler|
This table can be used with vim.fn.setqflist or vim.fn.setloclist. E.g.:
>lua
local function on_list(options)
vim.fn.setqflist({}, ' ', options)
vim.api.nvim_command('cfirst')
end
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.api.nvim_command('lopen')
end
<
================================================================================
LSP HIGHLIGHT *lsp-highlight*
@ -557,7 +532,7 @@ LspNotify *LspNotify*
LspProgress *LspProgress*
Upon receipt of a progress notification from the server. Notifications can
be polled from a `progress` ring buffer of a |vim.lsp.client| or use
be polled from a `progress` ring buffer of a |vim.lsp.Client| or use
|vim.lsp.status()| to get an aggregate message
If the server sends a "work done progress", the `pattern` is set to `kind`
@ -583,7 +558,7 @@ LspRequest *LspRequest*
will trigger with {type} == `cancel`.
When used from Lua, the client ID, request ID, and request are sent in
the "data" table. See {requests} in |vim.lsp.client| for details on the
the "data" table. See {requests} in |vim.lsp.Client| for details on the
{request} value. If the request type is `complete`, the request will be
deleted from the client's pending requests table immediately after
calling the event's callbacks. Example: >lua
@ -712,77 +687,6 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
(`string?`) err On timeout, cancel, or error, `err` is a string
describing the failure reason, and `result` is nil.
client *vim.lsp.client*
LSP client object. You can get an active client object via
|vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
• Methods:
• request(method, params, [handler], bufnr) Sends a request to the
server. This is a thin wrapper around {client.rpc.request} with some
additional checking. If {handler} is not specified, If one is not
found there, then an error will occur. Returns: {status},
{[client_id]}. {status} is a boolean indicating if the notification
was successful. If it is `false`, then it will always be `false` (the
client has shutdown). If {status} is `true`, the function returns
{request_id} as the second result. You can use this with
`client.cancel_request(request_id)` to cancel the request.
• request_sync(method, params, timeout_ms, bufnr) Sends a request to the
server and synchronously waits for the response. This is a wrapper
around {client.request} Returns: { err=err, result=result }, a
dictionary, where `err` and `result` come from the |lsp-handler|. On
timeout, cancel or error, returns `(nil, err)` where `err` is a string
describing the failure reason. If the request was unsuccessful returns
`nil`.
• notify(method, params) Sends a notification to an LSP server. Returns:
a boolean to indicate if the notification was successful. If it is
false, then it will always be false (the client has shutdown).
• cancel_request(id) Cancels a request with a given request id. Returns:
same as `notify()`.
• stop([force]) Stops a client, optionally with force. By default, it
will just ask the server to shutdown without force. If you request to
stop a client which has previously been requested to shutdown, it will
automatically escalate and force shutdown.
• is_stopped() Checks whether a client is stopped. Returns: true if the
client is fully stopped.
• on_attach(client, bufnr) Runs the on_attach function from the client's
config if it was defined. Useful for buffer-local setup.
• supports_method(method, [opts]): boolean Checks if a client supports a
given method. Always returns true for unknown off-spec methods. [opts]
is a optional `{bufnr?: integer}` table. Some language server
capabilities can be file specific.
• Members
• {id} (number): The id allocated to the client.
• {name} (string): If a name is specified on creation, that will be
used. Otherwise it is just the client id. This is used for logs and
messages.
• {rpc} (table): RPC client object, for low level interaction with the
client. See |vim.lsp.rpc.start()|.
• {offset_encoding} (string): The encoding used for communicating with
the server. You can modify this in the `config`'s `on_init` method
before text is sent to the server.
• {handlers} (table): The handlers used by the client as described in
|lsp-handler|.
• {commands} (table): Table of command name to function which is called
if any LSP action (code action, code lenses, ...) triggers the
command. Client commands take precedence over the global command
registry.
• {requests} (table): The current pending requests in flight to the
server. Entries are key-value pairs with the key being the request ID
while the value is a table with `type`, `bufnr`, and `method`
key-value pairs. `type` is either "pending" for an active request, or
"cancel" for a cancel request. It will be "complete" ephemerally while
executing |LspRequest| autocmds when replies are received from the
server.
• {config} (table): Reference of the table that was passed by the user
to |vim.lsp.start_client()|.
• {server_capabilities} (table): Response from the server sent on
`initialize` describing the server's capabilities.
• {progress} A ring buffer (|vim.ringbuf()|) containing progress
messages sent by the server.
• {settings} Map with language server specific settings. See {config} in
|vim.lsp.start_client()|
• {flags} A table with flags for the client. See {config} in
|vim.lsp.start_client()|
client_is_stopped({client_id}) *vim.lsp.client_is_stopped()*
Checks whether a client is stopped.
@ -820,10 +724,9 @@ formatexpr({opts}) *vim.lsp.formatexpr()*
'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
Parameters: ~
• {opts} (`table`) options for customizing the formatting expression
which takes the following optional keys:
• timeout_ms (default 500ms). The timeout period for the
formatting request.
• {opts} (`table?`) A table with the following fields:
• {timeout_ms} (`integer`, default: 500ms) The timeout period
for the formatting request..
*vim.lsp.get_buffers_by_client_id()*
get_buffers_by_client_id({client_id})
@ -843,23 +746,23 @@ get_client_by_id({client_id}) *vim.lsp.get_client_by_id()*
• {client_id} (`integer`) client id
Return: ~
(`lsp.Client?`) client rpc object
(`vim.lsp.Client?`) client rpc object
get_clients({filter}) *vim.lsp.get_clients()*
Get active clients.
Parameters: ~
• {filter} (`table?`) A table with key-value pairs used to filter the
returned clients. The available keys are:
id (number): Only return clients with the given id
bufnr (number): Only return clients attached to this
• {filter} (`table?`) Key-value pairs used to filter the returned
clients.
{id}? (`integer`) Only return clients with the given id
{bufnr}? (`integer`) Only return clients attached to this
buffer
• name (string): Only return clients with the given name
• method (string): Only return clients supporting the given
method
{name}? (`string`) Only return clients with the given name
{method}? (`string`) Only return clients supporting the
given method
Return: ~
(`lsp.Client[]`) List of |vim.lsp.client| objects
(`vim.lsp.Client[]`) List of |vim.lsp.Client| objects
get_log_path() *vim.lsp.get_log_path()*
Gets the path of the logfile used by the LSP client.
@ -937,15 +840,16 @@ start({config}, {opts}) *vim.lsp.start()*
`ftplugin/<filetype_name>.lua` (See |ftplugin-name|)
Parameters: ~
• {config} (`lsp.ClientConfig`) Same configuration as documented in
|vim.lsp.start_client()|
• {opts} (`lsp.StartOpts?`) Optional keyword arguments:
• reuse_client (fun(client: client, config: table): boolean)
Predicate used to decide if a client should be re-used.
Used on all running clients. The default implementation
re-uses a client if name and root_dir matches.
• bufnr (number) Buffer handle to attach to if starting or
re-using a client (0 for current).
• {config} (`vim.lsp.ClientConfig`) Configuration for the server. See
|vim.lsp.ClientConfig|.
• {opts} (`table?`) Optional keyword arguments
• {reuse_client} (`fun(client: vim.lsp.Client, config:
table): boolean`) Predicate used to decide if a client
should be re-used. Used on all running clients. The
default implementation re-uses a client if name and
root_dir matches.
• {bufnr} (`integer`) Buffer handle to attach to if starting
or re-using a client (0 for current).
Return: ~
(`integer?`) client_id
@ -953,112 +857,12 @@ start({config}, {opts}) *vim.lsp.start()*
start_client({config}) *vim.lsp.start_client()*
Starts and initializes a client with the given configuration.
Field `cmd` in {config} is required.
Parameters: ~
• {config} (`lsp.ClientConfig`) Configuration for the server:
• cmd: (string[]|fun(dispatchers: table):table) 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()|
• cmd_cwd: (string, default=|getcwd()|) Directory to launch
the `cmd` process. Not related to `root_dir`.
• cmd_env: (table) Environment flags to pass to the LSP on
spawn. Must be specified using a table. Non-string values
are coerced to string. Example: >
{ PORT = 8080; HOST = "0.0.0.0"; }
<
• detached: (boolean, default true) 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.
• workspace_folders: (table) 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.
• capabilities: 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.
• handlers: Map of language server method names to
|lsp-handler|
• settings: Map with language server specific settings.
These are returned to the language server if requested via
`workspace/configuration`. Keys are case-sensitive.
• commands: 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.
• init_options Values to pass in the initialization request
as `initializationOptions`. See `initialize` in the LSP
spec.
• name: (string, default=client-id) Name in log messages.
• get_language_id: function(bufnr, filetype) -> language ID
as string. Defaults to the filetype.
• offset_encoding: (default="utf-16") One of "utf-8",
"utf-16", or "utf-32" which is the encoding that the LSP
server expects. Client does not verify this is correct.
• on_error: Callback with parameters (code, ...), 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.
• before_init: Callback with parameters (initialize_params,
config) 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.
• on_init: Callback (client, initialize_result) 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.
• on_exit Callback (code, signal, client_id) invoked on
client exit.
• code: exit code of the process
• signal: number describing the signal used to terminate
(if any)
• client_id: client handle
• on_attach: Callback (client, bufnr) invoked when client
attaches to a buffer.
• trace: ("off" | "messages" | "verbose" | nil) passed
directly to the language server in the initialize request.
Invalid/empty values will default to "off"
• flags: 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.
• root_dir: (string) Directory where the LSP server will
base its workspaceFolders, rootUri, and rootPath on
initialization.
• {config} (`vim.lsp.ClientConfig`) Configuration for the server. See
|vim.lsp.ClientConfig|.
Return: ~
(`integer?`) client_id. |vim.lsp.get_client_by_id()| Note: client may
(`integer?`) client_id |vim.lsp.get_client_by_id()| Note: client may
not be fully initialized. Use `on_init` to do any actions once the
client has been initialized.
@ -1072,7 +876,7 @@ status() *vim.lsp.status()*
stop_client({client_id}, {force}) *vim.lsp.stop_client()*
Stops a client(s).
You can also use the `stop()` function on a |vim.lsp.client| object. To
You can also use the `stop()` function on a |vim.lsp.Client| object. To
stop all clients: >lua
vim.lsp.stop_client(vim.lsp.get_clients())
<
@ -1081,8 +885,8 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()*
for this client, then force-shutdown is attempted.
Parameters: ~
• {client_id} (`integer|table`) id or |vim.lsp.client| object, or list
thereof
• {client_id} (`integer|vim.lsp.Client`) id or |vim.lsp.Client| object,
or list thereof
• {force} (`boolean?`) shutdown forcefully
tagfunc({pattern}, {flags}) *vim.lsp.tagfunc()*
@ -1109,9 +913,281 @@ with({handler}, {override_config}) *vim.lsp.with()*
behavior of the {handler}
==============================================================================
Lua module: vim.lsp.client *lsp-client*
*vim.lsp.Client*
Fields: ~
• {id} (`integer`) The id allocated to the client.
• {name} (`string`) If a name is specified on creation,
that will be used. Otherwise it is just the
client id. This is used for logs and messages.
• {rpc} (`vim.lsp.rpc.PublicClient`) RPC client
object, for low level interaction with the
client. See |vim.lsp.rpc.start()|.
• {offset_encoding} (`string`) The encoding used for communicating
with the server. You can modify this in the
`config`'s `on_init` method before text is
sent to the server.
• {handlers} (`table<string,lsp.Handler>`) The handlers
used by the client as described in
|lsp-handler|.
• {requests} (`table<integer,{ type: string, bufnr: integer, method: string}>`)
The current pending requests in flight to the
server. Entries are key-value pairs with the
key being the request ID while the value is a
table with `type`, `bufnr`, and `method`
key-value pairs. `type` is either "pending"
for an active request, or "cancel" for a
cancel request. It will be "complete"
ephemerally while executing |LspRequest|
autocmds when replies are received from the
server.
• {config} (`vim.lsp.ClientConfig`) copy of the table
that was passed by the user to
|vim.lsp.start_client()|.
• {server_capabilities} (`lsp.ServerCapabilities?`) Response from the
server sent on initialize` describing the
server's capabilities.
• {progress} (`vim.lsp.Client.Progress`) A ring buffer
(|vim.ringbuf()|) containing progress messages
sent by the server.
• {initialized} (`true?`)
• {workspace_folders} (`lsp.WorkspaceFolder[]?`) The workspace
folders configured in the client when the
server starts. This property is only available
if the client supports workspace folders. It
can be `null` if the client supports workspace
folders but none are configured.
• {root_dir} (`string`)
• {attached_buffers} (`table<integer,true>`)
• {commands} (`table<string,fun(command: lsp.Command, ctx:
table)>`) Table of command name to function
which is called if any LSP action (code
action, code lenses, ...) triggers the
command. Client commands take precedence over
the global command registry.
• {settings} (`table`)
• {flags} (`table`)
• {get_language_id} (`fun(bufnr: integer, filetype: string): string`)
• {capabilities} (`lsp.ClientCapabilities`) The capabilities
provided by the client (editor or tool)
• {dynamic_capabilities} (`lsp.DynamicCapabilities`)
• {request} (`fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer): boolean, integer?`)
Sends a request to the server. This is a thin
wrapper around {client.rpc.request} with some
additional checking. If {handler} is not
specified, If one is not found there, then an
error will occur. Returns: {status},
{[client_id]}. {status} is a boolean
indicating if the notification was successful.
If it is `false`, then it will always be
`false` (the client has shutdown). If {status}
is `true`, the function returns {request_id}
as the second result. You can use this with
`client.cancel_request(request_id)` to cancel
the request.
• {request_sync} (`fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError?, result:any}?, string?`)
err # a dictionary, where
• {notify} (`fun(method: string, params: table?):
boolean`) Sends a notification to an LSP
server. Returns: a boolean to indicate if the
notification was successful. If it is false,
then it will always be false (the client has
shutdown).
• {cancel_request} (`fun(id: integer): boolean`) Cancels a
request with a given request id. Returns: same
as `notify()`.
• {stop} (`fun(force?: boolean)`) Stops a client,
optionally with force. By default, it will
just ask the server to shutdown without force.
If you request to stop a client which has
previously been requested to shutdown, it will
automatically escalate and force shutdown.
• {on_attach} (`fun(bufnr: integer)`) Runs the on_attach
function from the client's config if it was
defined. Useful for buffer-local setup.
• {supports_method} (`fun(method: string, opts?: {bufnr: integer?}): boolean`)
Checks if a client supports a given method.
Always returns true for unknown off-spec
methods. [opts] is a optional `{bufnr?:
integer}` table. Some language server
capabilities can be file specific.
• {is_stopped} (`fun(): boolean`) Checks whether a client is
stopped. Returns: true if the client is fully
stopped.
*vim.lsp.Client.Progress*
Extends: |vim.Ringbuf|
Fields: ~
• {pending} (`table<lsp.ProgressToken,lsp.LSPAny>`)
*vim.lsp.ClientConfig*
Fields: ~
• {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?`)
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()|
• {cmd_cwd}? (`string`, default: cwd) Directory to launch the
`cmd` process. Not related to `root_dir`.
• {cmd_env}? (`table`) 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"; }
<
• {detached}? (`boolean`, default: true) 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.
• {workspace_folders}? (`lsp.WorkspaceFolder[]`) 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.
• {capabilities}? (`lsp.ClientCapabilities`) 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.
• {handlers}? (`table<string,function>`) Map of language
server method names to |lsp-handler|
• {settings}? (`table`) Map with language server specific
settings. These are returned to the language
server if requested via
`workspace/configuration`. Keys are
case-sensitive.
• {commands}? (`table<string,fun(command: lsp.Command, ctx:
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.
• {init_options}? (`table`) Values to pass in the initialization
request as `initializationOptions`. See
`initialize` in the LSP spec.
• {name}? (`string`, default: client-id) Name in log
messages.
• {get_language_id}? (`fun(bufnr: integer, filetype: string):
string`) Language ID as string. Defaults to the
filetype.
• {offset_encoding}? (`'utf-8'|'utf-16'|'utf-32'`) The encoding that
the LSP server expects. Client does not verify
this is correct.
• {on_error}? (`fun(code: integer, err: string)`) 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.
• {before_init}? (`vim.lsp.client.before_init_cb`) 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.
• {on_init}? (`elem_or_list<vim.lsp.client.on_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.
• {on_exit}? (`elem_or_list<vim.lsp.client.on_exit_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
• {on_attach}? (`elem_or_list<vim.lsp.client.on_attach_cb>`)
Callback invoked when client attaches to a
buffer.
• {trace}? (`'off'|'messages'|'verbose'`, default: "off")
Passed directly to the language server in the
initialize request. Invalid/empty values will
• {flags}? (`table`) 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.
• {root_dir}? (`string`) Directory where the LSP server will
base its workspaceFolders, rootUri, and rootPath
on initialization.
==============================================================================
Lua module: vim.lsp.buf *lsp-buf*
*vim.lsp.ListOpts*
Fields: ~
• {on_list}? (`fun(t: vim.lsp.LocationOpts.OnList)`) 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
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
<
*vim.lsp.LocationOpts*
Extends: |vim.lsp.ListOpts|
Fields: ~
• {reuse_win}? (`boolean`) Jump to existing window if buffer is already
open.
*vim.lsp.LocationOpts.OnList*
Fields: ~
• {items} (`table[]`) Structured like |setqflist-what|
• {title}? (`string`) Title for the list.
• {context}? (`table`) `ctx` from |lsp-handler|
*vim.lsp.buf.add_workspace_folder()*
add_workspace_folder({workspace_folder})
Add the folder at path to the workspace folders. If {path} is not
@ -1127,27 +1203,26 @@ code_action({options}) *vim.lsp.buf.code_action()*
Selects a code action available at the current cursor position.
Parameters: ~
• {options} (`table?`) Optional table which holds the following
optional fields:
• context: (table|nil) Corresponds to `CodeActionContext`
of the LSP specification:
• diagnostics (table|nil): LSP `Diagnostic[]`. Inferred
• {options} (`table?`) A table with the following fields:
• {context}? (`lsp.CodeActionContext`) Corresponds to
`CodeActionContext` of the LSP specification:
• {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred
from the current position if not provided.
only (table|nil): List of LSP `CodeActionKind`s used to
{only}? (`table`) 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
{triggerKind}? (`integer`) 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
{filter}? (`fun(x: lsp.CodeAction|lsp.Command):boolean`)
Predicate taking an `CodeAction` and returning a boolean.
{apply}? (`boolean`) 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|
{range}? (`{start: integer[], end: integer[]}`) 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|
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
@ -1174,21 +1249,13 @@ declaration({options}) *vim.lsp.buf.declaration()*
|vim.lsp.buf.definition()| instead.
Parameters: ~
• {options} (`table?`) 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.
• {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
definition({options}) *vim.lsp.buf.definition()*
Jumps to the definition of the symbol under the cursor.
Parameters: ~
• {options} (`table?`) 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.
• {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
document_highlight() *vim.lsp.buf.document_highlight()*
Send request to the server to resolve document highlights for the current
@ -1208,15 +1275,13 @@ document_symbol({options}) *vim.lsp.buf.document_symbol()*
Lists all symbols in the current buffer in the quickfix window.
Parameters: ~
• {options} (`table?`) additional options
• on_list: (function) handler for list results. See
|lsp-on-list-handler|
• {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|.
execute_command({command_params}) *vim.lsp.buf.execute_command()*
Executes an LSP server command.
Parameters: ~
• {command_params} (`table`) A valid `ExecuteCommandParams` object
• {command_params} (`lsp.ExecuteCommandParams`)
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
@ -1226,38 +1291,37 @@ format({options}) *vim.lsp.buf.format()*
server clients.
Parameters: ~
• {options} (`table?`) Optional table which holds the following
optional fields:
• formatting_options (table|nil): Can be used to specify
• {options} (`table?`) A table with the following fields:
• {formatting_options}? (`table`) 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
{timeout_ms}? (`integer`, 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
}
if async=true.
{bufnr}? (`integer`, default: current buffer) Restrict
formatting to the clients attached to the given buffer.
• {filter}? (`fun(client: vim.lsp.Client): boolean?`)
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
{async}? (`boolean`, default: false) If true the method
won't block. Editing the buffer while formatting
asynchronous can lead to unexpected changes.
id (number|nil): Restrict formatting to the client with
{id}? (`integer`) Restrict formatting to the client with
ID (client.id) matching this field.
name (string|nil): Restrict formatting to the client with
{name}? (`string`) 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
{range}? (`{start:integer[],end:integer[]}`, default:
current selection in visual mode, `nil` in other modes,
formatting the full buffer) Range to format. Table must
contain `start` and `end` keys with {row,col} tuples
using (1,0) indexing.
hover() *vim.lsp.buf.hover()*
Displays hover information about the symbol under the cursor in a floating
@ -1268,9 +1332,7 @@ implementation({options}) *vim.lsp.buf.implementation()*
quickfix window.
Parameters: ~
• {options} (`table?`) additional options
• on_list: (function) |lsp-on-list-handler| replacing the
default handler. Called for any non-empty result.
• {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
incoming_calls() *vim.lsp.buf.incoming_calls()*
Lists all the call sites of the symbol under the cursor in the |quickfix|
@ -1291,9 +1353,7 @@ references({context}, {options}) *vim.lsp.buf.references()*
Parameters: ~
• {context} (`table?`) Context for the request
• {options} (`table?`) additional options
• on_list: (function) handler for list results. See
|lsp-on-list-handler|
• {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|.
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
@ -1312,11 +1372,12 @@ rename({new_name}, {options}) *vim.lsp.buf.rename()*
Parameters: ~
• {new_name} (`string?`) If not provided, the user will be prompted for
a new name using |vim.ui.input()|.
• {options} (`table?`) 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
• {options} (`table?`) Additional options:
• {filter}? (`fun(client: vim.lsp.Client): boolean?`)
Predicate used to filter clients. Receives a client as
argument and must return a boolean. Clients matching the
predicate are included.
• {name}? (`string`) Restrict clients used for rename to
ones where client.name matches this field.
signature_help() *vim.lsp.buf.signature_help()*
@ -1327,11 +1388,7 @@ type_definition({options}) *vim.lsp.buf.type_definition()*
Jumps to the definition of the type of the symbol under the cursor.
Parameters: ~
• {options} (`table?`) 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.
• {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
workspace_symbol({query}, {options}) *vim.lsp.buf.workspace_symbol()*
Lists all symbols in the current workspace in the quickfix window.
@ -1342,9 +1399,7 @@ workspace_symbol({query}, {options}) *vim.lsp.buf.workspace_symbol()*
Parameters: ~
• {query} (`string?`) optional
• {options} (`table?`) additional options
• on_list: (function) handler for list results. See
|lsp-on-list-handler|
• {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|.
==============================================================================
@ -1470,10 +1525,9 @@ refresh({opts}) *vim.lsp.codelens.refresh()*
<
Parameters: ~
• {opts} (`vim.lsp.codelens.RefreshOptions?`) Table with the following
fields:
• `bufnr` (integer|nil): filter by buffer. All buffers if nil,
0 for current buffer
• {opts} (`table?`) Optional fields
• {bufnr} (`integer?`) filter by buffer. All buffers if nil, 0
for current buffer
run() *vim.lsp.codelens.run()*
Run the code lens in the current line
@ -1525,17 +1579,15 @@ get({filter}) *vim.lsp.inlay_hint.get()*
• This API is pre-release (unstable).
Parameters: ~
• {filter} (`vim.lsp.inlay_hint.get.filter?`) Optional filters
|kwargs|:
• bufnr (integer?): 0 for current buffer
• range (lsp.Range?)
• {filter} (`table?`) Optional filters |kwargs|:
• {bufnr} (`integer?`)
• {range} (`lsp.Range?`)
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)
(`table[]`) A list of objects with the following fields:
• {bufnr} (`integer`)
• {client_id} (`integer`)
• {inlay_hint} (`lsp.InlayHint`)
is_enabled({bufnr}) *vim.lsp.inlay_hint.is_enabled()*
@ -1596,12 +1648,12 @@ highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts})
• {token} (`table`) a semantic token, found as `args.data.token` in
|LspTokenUpdate|.
• {bufnr} (`integer`) the buffer to highlight
• {client_id} (`integer`) The ID of the |vim.lsp.client|
• {client_id} (`integer`) The ID of the |vim.lsp.Client|
• {hl_group} (`string`) Highlight group name
• {opts} (`table?`) Optional parameters.
priority: (integer|nil) Priority for the applied
extmark. Defaults to
`vim.highlight.priorities.semantic_tokens + 3`
• {opts} (`table?`) Optional parameters:
{priority}? (`integer`, default:
`vim.highlight.priorities.semantic_tokens + 3`)
Priority for the applied extmark.
start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()*
Start the semantic token highlighting engine for the given buffer with the
@ -1841,7 +1893,12 @@ locations_to_items({locations}, {offset_encoding})
buffer
Return: ~
(`vim.lsp.util.LocationItem[]`) list of items
(`table[]`) A list of objects with the following fields:
• {filename} (`string`)
• {lnum} (`integer`) 1-indexed line number
• {col} (`integer`) 1-indexed column
• {text} (`string`)
• {user_data} (`lsp.Location|lsp.LocationLink`)
*vim.lsp.util.make_floating_popup_options()*
make_floating_popup_options({width}, {height}, {opts})
@ -1966,22 +2023,25 @@ open_floating_preview({contents}, {syntax}, {opts})
Parameters: ~
• {contents} (`table`) of lines to show in window
• {syntax} (`string`) of syntax to set for opened buffer
• {opts} (`table`) with optional fields (additional keys are
• {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
• {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}? (`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}
@ -2011,9 +2071,9 @@ rename({old_fname}, {new_fname}, {opts}) *vim.lsp.util.rename()*
Parameters: ~
• {old_fname} (`string`)
• {new_fname} (`string`)
• {opts} (`table?`) options
• overwrite? boolean
• ignoreIfExists? boolean
• {opts} (`table?`) Options:
{overwrite}? (`boolean`)
{ignoreIfExists}? (`boolean`)
*vim.lsp.util.show_document()*
show_document({location}, {offset_encoding}, {opts})
@ -2106,6 +2166,17 @@ should_log({level}) *vim.lsp.log.should_log()*
==============================================================================
Lua module: vim.lsp.rpc *lsp-rpc*
*vim.lsp.rpc.PublicClient*
Fields: ~
• {request} (`fun(method: string, params: table?, callback: fun(err: lsp.ResponseError?, result: any), notify_reply_callback: fun(integer)?):boolean,integer?`)
see |vim.lsp.rpc.request()|
• {notify} (`fun(method: string, params: any):boolean`) see
|vim.lsp.rpc.notify()|
• {is_closing} (`fun(): boolean`)
• {terminate} (`fun()`)
connect({host}, {port}) *vim.lsp.rpc.connect()*
Create a LSP RPC client factory that connects via TCP to the given host
and port.
@ -2199,28 +2270,31 @@ start({cmd}, {dispatchers}, {extra_spawn_params}) *vim.lsp.rpc.start()*
Parameters: ~
• {cmd} (`string[]`) Command to start the LSP server.
• {dispatchers} (`vim.lsp.rpc.Dispatchers?`) Dispatchers for LSP
message types. Valid dispatcher names are:
• `"notification"`
• `"server_request"`
• `"on_error"`
• `"on_exit"`
• {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
• {dispatchers} (`table?`) Dispatchers for LSP message types.
• {notification} (`fun(method: string, params:
table)`)
• {server_request} (`fun(method: string, params:
table): any?, lsp.ResponseError?`)
• {on_exit} (`fun(code: integer, signal:
integer)`)
• {on_error} (`fun(code: integer, err: any)`)
• {extra_spawn_params} (`table?`) Additional context for the LSP server
process.
• {cwd}? (`string`) Working directory for the
LSP server process
• {detached}? (`boolean`) Detach the LSP server
process from the current process
• {env}? (`table<string,string>`) Additional
environment variables for LSP server process.
See |vim.system()|
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.
• `terminate()` terminates the RPC client.
• `terminate()` terminates the RPC client. See
|vim.lsp.rpc.PublicClient|.
==============================================================================

View File

@ -1828,16 +1828,16 @@ vim.inspect_pos({bufnr}, {row}, {col}, {filter}) *vim.inspect_pos()*
the current cursor
• {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
the current cursor
• {filter} (`table?`) a table with key-value pairs to filter the items
• syntax (boolean): include syntax based highlight groups
(defaults to true)
• treesitter (boolean): include treesitter based highlight
groups (defaults to true)
• extmarks (boolean|"all"): include extmarks. When `all`,
then extmarks without a `hl_group` will also be included
(defaults to true)
• semantic_tokens (boolean): include semantic tokens
• {filter} (`table?`) Table with key-value pairs to filter the items
• {syntax} (`boolean`) Include syntax based highlight groups
(defaults to true)
• {treesitter} (`boolean`) Include treesitter based
highlight groups (defaults to true)
• {extmarks} (`boolean|"all"`, default: true) Include
extmarks. When `all`, then extmarks without a `hl_group`
will also be included.
• {semantic_tokens} (`boolean`) Include semantic token
highlights (defaults to true)
Return: ~
(`table`) a table with the following key-value pairs. Items are in
@ -1866,6 +1866,17 @@ vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()*
*vim.Ringbuf*
Fields: ~
• {clear} (`fun()`) Clear all items
• {push} (`fun(item: T)`) Adds an item, overriding the oldest item if
the buffer is full.
• {pop} (`fun(): T?`) Removes and returns the first unread item
• {peek} (`fun(): T?`) Returns the first unread item without removing
it
Ringbuf:clear() *Ringbuf:clear()*
Clear all items
@ -1970,9 +1981,10 @@ vim.gsplit({s}, {sep}, {opts}) *vim.gsplit()*
• {s} (`string`) String to split
• {sep} (`string`) Separator or pattern
• {opts} (`table?`) Keyword arguments |kwargs|:
• plain: (boolean) Use `sep` literally (as in string.find).
• trimempty: (boolean) Discard empty segments at start and end
of the sequence.
• {plain}? (`boolean`) Use `sep` literally (as in
string.find).
• {trimempty}? (`boolean`) Discard empty segments at start and
end of the sequence.
Return: ~
(`function`) Iterator over the split components
@ -2104,8 +2116,11 @@ vim.split({s}, {sep}, {opts}) *vim.split()*
Parameters: ~
• {s} (`string`) String to split
• {sep} (`string`) Separator or pattern
• {opts} (`table?`) Keyword arguments |kwargs| accepted by
|vim.gsplit()|
• {opts} (`table?`) Keyword arguments |kwargs|:
• {plain}? (`boolean`) Use `sep` literally (as in
string.find).
• {trimempty}? (`boolean`) Discard empty segments at start and
end of the sequence.
Return: ~
(`string[]`) List of split components
@ -2151,8 +2166,8 @@ vim.tbl_contains({t}, {value}, {opts}) *vim.tbl_contains()*
• {t} (`table`) Table to check
• {value} (`any`) Value to compare or predicate function reference
• {opts} (`table?`) Keyword arguments |kwargs|:
predicate: (boolean) `value` is a function reference to be
checked (default false)
{predicate}? (`boolean`) `value` is a function reference to
be checked (default false)
Return: ~
(`boolean`) `true` if `t` contains `value`
@ -2419,23 +2434,23 @@ vim.loader.find({modname}, {opts}) *vim.loader.find()*
• {modname} (`string`) Module name, or `"*"` to find the top-level
modules instead
• {opts} (`table?`) Options for finding a module:
rtp: (boolean) Search for modname in the runtime path
(defaults to `true`)
paths: (string[]) Extra paths to search for modname
(defaults to `{}`)
patterns: (string[]) List of patterns to use when
searching for modules. A pattern is a string added to the
basename of the Lua module being searched. (defaults to
`{"/init.lua", ".lua"}`)
all: (boolean) Return all matches instead of just the
first one (defaults to `false`)
{rtp}? (`boolean`, default: `true`) Search for modname in
the runtime path.
{paths}? (`string[]`, default: `{}`) Extra paths to
search for modname
{patterns}? (`string[]`, default: `{"/init.lua",
".lua"}`) List of patterns to use when searching for
modules. A pattern is a string added to the basename of
the Lua module being searched.
{all}? (`boolean`, default: `false`) Search for all
matches.
Return: ~
(`table`) A list of results with the following properties:
modpath: (string) the path to the module
modname: (string) the name of the module
stat: (table|nil) the fs_stat of the module path. Won't be returned
for `modname="*"`
(`table[]`) A list of objects with the following fields:
{modpath} (`string`) Path of the module
{modname} (`string`) Name of the module
{stat}? (`uv.uv_fs_t`) The fs_stat of the module path. Won't be
returned for `modname="*"`
vim.loader.reset({path}) *vim.loader.reset()*
Resets the cache for the path, or all the paths if path is nil.
@ -2678,6 +2693,9 @@ vim.filetype.add({filetypes}) *vim.filetype.add()*
Parameters: ~
• {filetypes} (`table`) A table containing new filetype maps (see
example).
• {pattern}? (`vim.filetype.mapping`)
• {extension}? (`vim.filetype.mapping`)
• {filename}? (`vim.filetype.mapping`)
*vim.filetype.get_option()*
vim.filetype.get_option({filetype}, {option})
@ -2734,16 +2752,16 @@ vim.filetype.match({args}) *vim.filetype.match()*
Parameters: ~
• {args} (`table`) Table specifying which matching strategy to use.
Accepted keys are:
buf (number): Buffer number to use for matching. Mutually
exclusive with {contents}
• filename (string): Filename to use for matching. When {buf}
is given, defaults to the filename of the given buffer
{buf}? (`integer`) Buffer number to use for matching.
Mutually exclusive with {contents}
{filename}? (`string`) Filename to use for matching. When
{buf} is given, defaults to the filename of the given buffer
number. The file need not actually exist in the filesystem.
When used without {buf} only the name of the file is used
for filetype matching. This may result in failure to detect
the filetype in cases where the filename alone is not enough
to disambiguate the filetype.
contents (table): An array of lines representing file
{contents}? (`string[]`) An array of lines representing file
contents to use for matching. Can be used with {filename}.
Mutually exclusive with {buf}.
@ -2896,18 +2914,18 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
• path: full path of the current item The function should
return `true` if the given item is considered a match.
• {opts} (`table`) Optional keyword arguments:
• path (string): Path to begin searching from. If omitted,
{path} (`string`) Path to begin searching from. If omitted,
the |current-directory| is used.
upward (boolean, default false): If true, search upward
{upward} (`boolean`, default: `false`) Search upward
through parent directories. Otherwise, search through child
directories (recursively).
• stop (string): Stop searching when this directory is
{stop} (`string`) Stop searching when this directory is
reached. The directory itself is not searched.
• type (string): Find only items of the given type. If
{type} (`string`) Find only items of the given type. If
omitted, all items that match {names} are included.
• limit (number, default 1): Stop the search after finding
this many matches. Use `math.huge` to place no limit on the
number of matches.
{limit} (`number`, default: `1`) Stop the search after
finding this many matches. Use `math.huge` to place no
limit on the number of matches.
Return: ~
(`string[]`) Normalized paths |vim.fs.normalize()| of all matching
@ -2942,9 +2960,9 @@ vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
Parameters: ~
• {path} (`string`) Path to normalize
• {opts} (`table?`) Options:
expand_env: boolean Expand environment variables (default:
true)
• {opts} (`table?`) A table with the following fields:
{expand_env} (`boolean`, default: `true`) Expand environment
variables.
Return: ~
(`string`) Normalized path
@ -3538,14 +3556,15 @@ vim.secure.trust({opts}) *vim.secure.trust()*
The trust database is located at |$XDG_STATE_HOME|/nvim/trust.
Parameters: ~
• {opts} (`table`)
• action (string): "allow" to add a file to the trust database
and trust it, "deny" to add a file to the trust database and
deny it, "remove" to remove file from the trust database
• path (string|nil): Path to a file to update. Mutually
• {opts} (`table?`) A table with the following fields:
• {action} (`'allow'|'deny'|'remove'`) - `'allow'` to add a
file to the trust database and trust it,
• `'deny'` to add a file to the trust database and deny it,
• `'remove'` to remove file from the trust database
• {path}? (`string`) Path to a file to update. Mutually
exclusive with {bufnr}. Cannot be used when {action} is
"allow".
bufnr (number|nil): Buffer number to update. Mutually
{bufnr}? (`integer`) Buffer number to update. Mutually
exclusive with {path}.
Return (multiple): ~
@ -3628,8 +3647,8 @@ vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
otherwise-equivalent versions.
Parameters: ~
• {v1} (`Version|number[]|string`) Version object.
• {v2} (`Version|number[]|string`) Version to compare with `v1`.
• {v1} (`vim.Version|number[]|string`) Version object.
• {v2} (`vim.Version|number[]|string`) Version to compare with `v1`.
Return: ~
(`integer`) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
@ -3639,8 +3658,8 @@ vim.version.eq({v1}, {v2}) *vim.version.eq()*
for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
• {v2} (`Version|number[]|string`)
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
@ -3649,8 +3668,8 @@ vim.version.ge({v1}, {v2}) *vim.version.ge()*
Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
• {v2} (`Version|number[]|string`)
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
@ -3659,8 +3678,8 @@ vim.version.gt({v1}, {v2}) *vim.version.gt()*
Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
• {v2} (`Version|number[]|string`)
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
@ -3669,17 +3688,17 @@ vim.version.last({versions}) *vim.version.last()*
TODO: generalize this, move to func.lua
Parameters: ~
• {versions} (`Version[]`)
• {versions} (`vim.Version[]`)
Return: ~
(`Version?`)
(`vim.Version?`)
vim.version.le({v1}, {v2}) *vim.version.le()*
Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
• {v2} (`Version|number[]|string`)
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
@ -3688,8 +3707,8 @@ vim.version.lt({v1}, {v2}) *vim.version.lt()*
Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
• {v2} (`Version|number[]|string`)
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
@ -3710,7 +3729,7 @@ vim.version.parse({version}, {opts}) *vim.version.parse()*
"1.0", "0-x", "tmux 3.2a" into valid versions.
Return: ~
(`Version?`) parsed_version Version object or `nil` if input is
(`vim.Version?`) parsed_version Version object or `nil` if input is
invalid.
See also: ~
@ -3744,6 +3763,12 @@ vim.version.range({spec}) *vim.version.range()*
Parameters: ~
• {spec} (`string`) Version range "spec"
Return: ~
(`table`) A table with the following fields:
• {from} (`vim.Version`)
• {to}? (`vim.Version`)
• {has} (`fun(self: vim.VersionRangeversion: string|vim.Version)`)
See also: ~
• https://github.com/npm/node-semver#ranges
@ -4380,15 +4405,15 @@ tohtml.tohtml({winid}, {opt}) *tohtml.tohtml.tohtml()*
Parameters: ~
• {winid} (`integer?`) Window to convert (defaults to current window)
• {opt} (`table?`) Optional parameters.
title (string): Title tag to set in the generated HTML code
(defaults to buffer name)
• number_lines (boolean): Show line numbers (defaults to
`false`)
font (string|string[]): Fonts to use (defaults to
`guifont`)
width (integer) Width used for items which are either right
aligned or repeat a character infinitely (defaults to
'textwidth' if non-zero or window width otherwise)
{title}? (`string|false`, default: buffer name) Title tag
to set in the generated HTML code.
{number_lines}? (`boolean`, default: `false`) Show line
numbers.
{font}? (`string[]|string`, default: `guifont`) Fonts to
use.
{width}? (`integer`, default: 'textwidth' if non-zero or
window width otherwise) Width used for items which are
either right aligned or repeat a character infinitely.
Return: ~
(`string[]`)

View File

@ -732,16 +732,16 @@ get_node({opts}) *vim.treesitter.get_node()*
<
Parameters: ~
• {opts} (`vim.treesitter.GetNodeOpts?`) Optional keyword arguments:
bufnr integer|nil Buffer number (nil or 0 for current
• {opts} (`table?`) Optional keyword arguments:
{bufnr} (`integer?`) Buffer number (nil or 0 for current
buffer)
pos table|nil 0-indexed (row, col) tuple. Defaults to cursor
position in the current window. Required if {bufnr} is not
the current buffer
lang string|nil Parser language. (default: from buffer
{pos} (`{ [1]: integer, [2]: integer }?`) 0-indexed (row,
col) tuple. Defaults to cursor position in the current
window. Required if {bufnr} is not the current buffer
{lang} (`string?`) Parser language. (default: from buffer
filetype)
• ignore_injections boolean Ignore injected languages (default
true)
{ignore_injections} (`boolean?`) Ignore injected languages
(default true)
Return: ~
(`TSNode?`) Node at the given position
@ -787,7 +787,7 @@ get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()*
• {opts} (`table?`) Options to pass to the created language tree
Return: ~
(`LanguageTree`) object to use for parsing
(`vim.treesitter.LanguageTree`) object to use for parsing
get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()*
Get the range of a |TSNode|. Can also supply {source} and {metadata} to
@ -797,7 +797,7 @@ get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()*
• {node} (`TSNode`)
• {source} (`integer|string?`) Buffer or string from which the {node}
is extracted
• {metadata} (`TSMetadata?`)
• {metadata} (`vim.treesitter.query.TSMetadata?`)
Return: ~
(`Range6`)
@ -812,7 +812,7 @@ get_string_parser({str}, {lang}, {opts})
• {opts} (`table?`) Options to pass to the created language tree
Return: ~
(`LanguageTree`) object to use for parsing
(`vim.treesitter.LanguageTree`) object to use for parsing
inspect_tree({opts}) *vim.treesitter.inspect_tree()*
Open a window that displays a textual representation of the nodes in the
@ -917,10 +917,10 @@ add({lang}, {opts}) *vim.treesitter.language.add()*
Parameters: ~
• {lang} (`string`) Name of the parser (alphanumerical and `_` only)
• {opts} (`table?`) Options:
filetype (string|string[]) Default filetype the parser
should be associated with. Defaults to {lang}.
path (string|nil) Optional path the parser is located at
symbol_name (string|nil) Internal symbol name for the
{filetype}? (`string|string[]`, default: {lang}) Default
filetype the parser should be associated with.
{path}? (`string`) Optional path the parser is located at
{symbol_name}? (`string`) Internal symbol name for the
language to load
get_filetypes({lang}) *vim.treesitter.language.get_filetypes()*
@ -1069,10 +1069,10 @@ lint({buf}, {opts}) *vim.treesitter.query.lint()*
Parameters: ~
• {buf} (`integer`) Buffer handle
• {opts} (`table?`) Optional keyword arguments:
langs (string|string[]|nil) Language(s) to use for checking
{langs}? (`string|string[]`) Language(s) to use for checking
the query. If multiple languages are specified, queries are
validated for all of them
clear (boolean) if `true`, just clear current lint errors
{clear} (`boolean`) Just clear current lint errors
list_directives() *vim.treesitter.query.list_directives()*
Lists the currently available directives to use in queries.
@ -1153,8 +1153,8 @@ Query:iter_captures({node}, {source}, {start}, {stop})
Defaults to `node:end_()`.
Return: ~
(`fun(end_line: integer?): integer, TSNode, TSMetadata`) capture id,
capture node, metadata
(`fun(end_line: integer?): integer, TSNode,
vim.treesitter.query.TSMetadata`) capture id, capture node, metadata
*Query:iter_matches()*
Query:iter_matches({node}, {source}, {start}, {stop}, {opts})
@ -1279,7 +1279,7 @@ LanguageTree:for_each_tree({fn}) *LanguageTree:for_each_tree()*
Note: This includes the invoking tree's child trees as well.
Parameters: ~
• {fn} (`fun(tree: TSTree, ltree: LanguageTree)`)
• {fn} (`fun(tree: TSTree, ltree: vim.treesitter.LanguageTree)`)
LanguageTree:included_regions() *LanguageTree:included_regions()*
Gets the set of included regions managed by this LanguageTree. This can be
@ -1318,7 +1318,7 @@ LanguageTree:language_for_range({range})
• {range} (`Range4`) `{ start_line, start_col, end_line, end_col }`
Return: ~
(`LanguageTree`) Managing {range}
(`vim.treesitter.LanguageTree`) Managing {range}
*LanguageTree:named_node_for_range()*
LanguageTree:named_node_for_range({range}, {opts})

View File

@ -25,13 +25,7 @@
-- Remarks:
-- - Not all visuals are supported, so it may differ.
--- @class vim.tohtml.opt
--- @field title? string|false
--- @field number_lines? boolean
--- @field font? string[]|string
--- @field width? integer
--- @class vim.tohtml.state.global
--- @class (private) vim.tohtml.state.global
--- @field background string
--- @field foreground string
--- @field title string|false
@ -39,7 +33,7 @@
--- @field highlights_name table<integer,string>
--- @field conf vim.tohtml.opt
--- @class vim.tohtml.state:vim.tohtml.state.global
--- @class (private) vim.tohtml.state:vim.tohtml.state.global
--- @field style vim.tohtml.styletable
--- @field tabstop string|false
--- @field opt vim.wo
@ -48,20 +42,20 @@
--- @field width integer
--- @field buflen integer
--- @class vim.tohtml.styletable
--- @class (private) vim.tohtml.styletable
--- @field [integer] vim.tohtml.line (integer: (1-index, exclusive))
--- @class vim.tohtml.line
--- @class (private) vim.tohtml.line
--- @field virt_lines {[integer]:{[1]:string,[2]:integer}[]}
--- @field pre_text string[][]
--- @field hide? boolean
--- @field [integer] vim.tohtml.cell? (integer: (1-index, exclusive))
--- @class vim.tohtml.cell
--- @class (private) vim.tohtml.cell
--- @field [1] integer[] start
--- @field [2] integer[] close
--- @field [3] any[][] virt_text
--- @field [4] any[][] overlay_text
--- @field [3] any[][] virt_text
--- @field [4] any[][] overlay_text
local HIDE_ID = -1
-- stylua: ignore start
@ -1319,14 +1313,29 @@ end
local M = {}
--- @class vim.tohtml.opt
--- @inlinedoc
---
--- Title tag to set in the generated HTML code.
--- (default: buffer name)
--- @field title? string|false
---
--- Show line numbers.
--- (default: `false`)
--- @field number_lines? boolean
---
--- Fonts to use.
--- (default: `guifont`)
--- @field font? string[]|string
---
--- Width used for items which are either right aligned or repeat a character
--- infinitely.
--- (default: 'textwidth' if non-zero or window width otherwise)
--- @field width? integer
--- Converts the buffer shown in the window {winid} to HTML and returns the output as a list of string.
--- @param winid? integer Window to convert (defaults to current window)
--- @param opt? vim.tohtml.opt (table) Optional parameters.
--- - title (string): Title tag to set in the generated HTML code (defaults to buffer name)
--- - number_lines (boolean): Show line numbers (defaults to `false`)
--- - font (string|string[]): Fonts to use (defaults to `guifont`)
--- - width (integer) Width used for items which are either right aligned or repeat a character infinitely
--- (defaults to 'textwidth' if non-zero or window width otherwise)
--- @param opt? vim.tohtml.opt Optional parameters.
--- @return string[]
function M.tohtml(winid, opt)
return win_to_html(winid or 0, opt)

View File

@ -190,6 +190,7 @@ function vim._os_proc_children(ppid)
return children
end
--- @nodoc
--- @class vim.inspect.Opts
--- @field depth? integer
--- @field newline? string
@ -454,7 +455,7 @@ vim.cmd = setmetatable({}, {
end,
})
--- @class vim.var_accessor
--- @class (private) vim.var_accessor
--- @field [string] any
--- @field [integer] vim.var_accessor
@ -1048,7 +1049,7 @@ function vim.deprecate(name, alternative, version, plugin, backtrace)
-- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev),
-- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev).
if plugin == 'Nvim' then
local current_version = vim.version() ---@type Version
local current_version = vim.version() ---@type vim.Version
local removal_version = assert(vim.version.parse(version))
local is_hard_deprecated ---@type boolean

View File

@ -1,8 +1,18 @@
---@class InspectorFilter
---@field syntax boolean include syntax based highlight groups (defaults to true)
---@field treesitter boolean include treesitter based highlight groups (defaults to true)
---@field extmarks boolean|"all" include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
---@field semantic_tokens boolean include semantic token highlights (defaults to true)
--- @class vim._inspector.Filter
--- @inlinedoc
---
--- Include syntax based highlight groups (defaults to true)
--- @field syntax boolean
---
--- Include treesitter based highlight groups (defaults to true)
--- @field treesitter boolean
---
--- Include extmarks. When `all`, then extmarks without a `hl_group` will also be included.
--- (default: true)
--- @field extmarks boolean|"all"
---
--- Include semantic token highlights (defaults to true)
--- @field semantic_tokens boolean
local defaults = {
syntax = true,
treesitter = true,
@ -17,11 +27,7 @@ local defaults = {
---@param bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
---@param filter? InspectorFilter (table) a table with key-value pairs to filter the items
--- - syntax (boolean): include syntax based highlight groups (defaults to true)
--- - treesitter (boolean): include treesitter based highlight groups (defaults to true)
--- - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
--- - semantic_tokens (boolean): include semantic tokens (defaults to true)
---@param filter? vim._inspector.Filter Table with key-value pairs to filter the items
---@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:integer,col:integer,row:integer} (table) a table with the following key-value pairs. Items are in "traversal order":
--- - treesitter: a list of treesitter captures
--- - syntax: a list of syntax groups
@ -139,7 +145,7 @@ end
---@param bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
---@param filter? InspectorFilter (table) see |vim.inspect_pos()|
---@param filter? vim._inspector.Filter (table) see |vim.inspect_pos()|
function vim.show_pos(bufnr, row, col, filter)
local items = vim.inspect_pos(bufnr, row, col, filter)

View File

@ -61,6 +61,7 @@ error('Cannot require a meta file')
---
--- </pre>
---@nodoc
---@class vim.NIL
---@type vim.NIL

View File

@ -21,6 +21,7 @@ error('Cannot require a meta file')
vim.lpeg = {}
--- @nodoc
--- @class vim.lpeg.Pattern
--- @operator unm: vim.lpeg.Pattern
--- @operator add(vim.lpeg.Pattern): vim.lpeg.Pattern
@ -167,6 +168,7 @@ function vim.lpeg.S(string) end
--- @return vim.lpeg.Pattern
function vim.lpeg.V(v) end
--- @nodoc
--- @class vim.lpeg.Locale
--- @field alnum userdata
--- @field alpha userdata

View File

@ -12,6 +12,7 @@
--- @return vim.regex
function vim.regex(re) end
--- @nodoc
--- @class vim.regex
local regex = {} -- luacheck: no unused

View File

@ -797,6 +797,7 @@ end
--- `vim.opt_global`.
--- </pre>
--- @nodoc
--- @class vim.Option
local Option = {} -- luacheck: no unused

View File

@ -2,18 +2,44 @@ local api, if_nil = vim.api, vim.F.if_nil
local M = {}
--- *diagnostic-structure*
---
--- Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based
--- rows and columns). |api-indexing|
--- @class vim.Diagnostic
---
--- Buffer number
--- @field bufnr? integer
--- @field lnum integer 0-indexed
--- @field end_lnum? integer 0-indexed
--- @field col integer 0-indexed
--- @field end_col? integer 0-indexed
---
--- The starting line of the diagnostic (0-indexed)
--- @field lnum integer
---
--- The final line of the diagnostic (0-indexed)
--- @field end_lnum? integer
---
--- The starting column of the diagnostic (0-indexed)
--- @field col integer
---
--- The final column of the diagnostic (0-indexed)
--- @field end_col? integer
---
--- The severity of the diagnostic |vim.diagnostic.severity|
--- @field severity? vim.diagnostic.Severity
---
--- The diagnostic text
--- @field message string
---
--- The source of the diagnostic
--- @field source? string
---
--- The diagnostic code
--- @field code? string|integer
---
--- @field _tags? { deprecated: boolean, unnecessary: boolean}
---
--- Arbitrary data plugins or users can add
--- @field user_data? any arbitrary data plugins can add
---
--- @field namespace? integer
--- @class vim.diagnostic.Opts
@ -104,7 +130,7 @@ local global_diagnostic_options = {
severity_sort = false,
}
--- @class vim.diagnostic.Handler
--- @class (private) vim.diagnostic.Handler
--- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved)
--- @field hide? fun(namespace:integer, bufnr:integer)
@ -154,7 +180,7 @@ do
})
end
--- @class vim.diagnostic._extmark
--- @class (private) vim.diagnostic._extmark
--- @field [1] integer id
--- @field [2] integer start
--- @field [3] integer end
@ -1018,31 +1044,52 @@ function M.get_next_pos(opts)
return { next.lnum, next.col }
end
--- A table with the following keys:
--- @class vim.diagnostic.GetOpts
--- @inlinedoc
---
--- Limit diagnostics to the given namespace.
--- @field namespace? integer
---
--- Limit diagnostics to the given line number.
--- @field lnum? integer
---
--- See |diagnostic-severity|.
--- @field severity? vim.diagnostic.SeverityFilter
--- Configuration table with the following keys:
--- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts
--- @inlinedoc
---
--- Only consider diagnostics from the given namespace.
--- @field namespace integer
---
--- Cursor position as a (row, col) tuple.
--- See |nvim_win_get_cursor()|. Defaults to the current cursor position.
--- @field cursor_position? {[1]:integer,[2]:integer}
---
--- Whether to loop around file or not. Similar to 'wrapscan'.
--- (default: `true`)
--- @field wrap? boolean
---
--- See |diagnostic-severity|.
--- @field severity vim.diagnostic.Severity
---
--- If "true", call |vim.diagnostic.open_float()|
--- after moving. If a table, pass the table as the {opts} parameter
--- to |vim.diagnostic.open_float()|. Unless overridden, the float will show
--- diagnostics at the new cursor position (as if "cursor" were passed to
--- the "scope" option).
--- (default: `true`)
--- @field float? boolean|vim.diagnostic.Opts.Float
---
--- Window ID
--- (default: `0`)
--- @field win_id? integer
--- Move to the next diagnostic.
---
---@param opts? vim.diagnostic.GotoOpts (table) Configuration table with the following keys:
--- - namespace: (integer) Only consider diagnostics from the given namespace.
--- - cursor_position: (cursor position) Cursor position as a (row, col) tuple.
--- See |nvim_win_get_cursor()|. Defaults to the current cursor position.
--- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'.
--- - severity: See |diagnostic-severity|.
--- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()|
--- after moving. If a table, pass the table as the {opts} parameter
--- to |vim.diagnostic.open_float()|. Unless overridden, the float will show
--- diagnostics at the new cursor position (as if "cursor" were passed to
--- the "scope" option).
--- - win_id: (number, default 0) Window ID
---@param opts? vim.diagnostic.GotoOpts
function M.goto_next(opts)
diagnostic_move_pos(opts, M.get_next_pos(opts))
end
@ -1789,38 +1836,54 @@ function M.reset(namespace, bufnr)
end
end
--- Configuration table with the following keys:
--- @class vim.diagnostic.setqflist.Opts
--- @inlinedoc
---
--- Only add diagnostics from the given namespace.
--- @field namespace? integer
---
--- Open quickfix list after setting.
--- (default: `true`)
--- @field open? boolean
---
--- Title of quickfix list. Defaults to "Diagnostics".
--- @field title? string
---
--- See |diagnostic-severity|.
--- @field severity? vim.diagnostic.Severity
--- Add all diagnostics to the quickfix list.
---
---@param opts? vim.diagnostic.setqflist.Opts (table) Configuration table with the following keys:
--- - namespace: (number) Only add diagnostics from the given namespace.
--- - open: (boolean, default true) Open quickfix list after setting.
--- - title: (string) Title of quickfix list. Defaults to "Diagnostics".
--- - severity: See |diagnostic-severity|.
---@param opts? vim.diagnostic.setqflist.Opts
function M.setqflist(opts)
set_list(false, opts)
end
---Configuration table with the following keys:
--- @class vim.diagnostic.setloclist.Opts
--- @inlinedoc
---
--- Only add diagnostics from the given namespace.
--- @field namespace? integer
--- @field open? boolean
--- @field title? string
--- @field severity? vim.diagnostic.Severity
---
--- Window number to set location list for.
--- (default: `0`)
--- @field winnr? integer
---
--- Open the location list after setting.
--- (default: `true`)
--- @field open? boolean
---
--- Title of the location list. Defaults to "Diagnostics".
--- @field title? string
---
--- See |diagnostic-severity|.
--- @field severity? vim.diagnostic.Severity
--- Add buffer diagnostics to the location list.
---
---@param opts? vim.diagnostic.setloclist.Opts (table) Configuration table with the following keys:
--- - namespace: (number) Only add diagnostics from the given namespace.
--- - winnr: (number, default 0) Window number to set location list for.
--- - open: (boolean, default true) Open the location list after setting.
--- - title: (string) Title of the location list. Defaults to "Diagnostics".
--- - severity: See |diagnostic-severity|.
---@param opts? vim.diagnostic.setloclist.Opts
function M.setloclist(opts)
set_list(true, opts)
end

View File

@ -2082,6 +2082,7 @@ local function normalize_path(path, as_pattern)
end
--- @class vim.filetype.add.filetypes
--- @inlinedoc
--- @field pattern? vim.filetype.mapping
--- @field extension? vim.filetype.mapping
--- @field filename? vim.filetype.mapping
@ -2170,7 +2171,7 @@ end
--- }
--- ```
---
---@param filetypes vim.filetype.add.filetypes (table) A table containing new filetype maps (see example).
---@param filetypes vim.filetype.add.filetypes A table containing new filetype maps (see example).
function M.add(filetypes)
for k, v in pairs(filetypes.extension or {}) do
extension[k] = v
@ -2272,8 +2273,23 @@ local function match_pattern(name, path, tail, pat)
end
--- @class vim.filetype.match.args
--- @inlinedoc
---
--- Buffer number to use for matching. Mutually exclusive with {contents}
--- @field buf? integer
---
--- Filename to use for matching. When {buf} is given,
--- defaults to the filename of the given buffer number. The
--- file need not actually exist in the filesystem. When used
--- without {buf} only the name of the file is used for
--- filetype matching. This may result in failure to detect
--- the filetype in cases where the filename alone is not
--- enough to disambiguate the filetype.
--- @field filename? string
---
--- An array of lines representing file contents to use for
--- matching. Can be used with {filename}. Mutually exclusive
--- with {buf}.
--- @field contents? string[]
--- Perform filetype detection.
@ -2305,20 +2321,8 @@ end
--- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} })
--- ```
---
---@param args vim.filetype.match.args (table) Table specifying which matching strategy to use.
---@param args vim.filetype.match.args Table specifying which matching strategy to use.
--- Accepted keys are:
--- * buf (number): Buffer number to use for matching. Mutually exclusive with
--- {contents}
--- * filename (string): Filename to use for matching. When {buf} is given,
--- defaults to the filename of the given buffer number. The
--- file need not actually exist in the filesystem. When used
--- without {buf} only the name of the file is used for
--- filetype matching. This may result in failure to detect
--- the filetype in cases where the filename alone is not
--- enough to disambiguate the filetype.
--- * contents (table): An array of lines representing file contents to use for
--- matching. Can be used with {filename}. Mutually exclusive
--- with {buf}.
---@return string|nil # If a match was found, the matched filetype.
---@return function|nil # A function that modifies buffer state when called (for example, to set some
--- filetype specific buffer variables). The function accepts a buffer number as

View File

@ -147,11 +147,29 @@ function M.dir(path, opts)
end)
end
--- @class vim.fs.find.opts
--- @class vim.fs.find.Opts
--- @inlinedoc
---
--- Path to begin searching from. If
--- omitted, the |current-directory| is used.
--- @field path string
---
--- Search upward through parent directories.
--- Otherwise, search through child directories (recursively).
--- (default: `false`)
--- @field upward boolean
---
--- Stop searching when this directory is reached.
--- The directory itself is not searched.
--- @field stop string
---
--- Find only items of the given type.
--- If omitted, all items that match {names} are included.
--- @field type string
---
--- Stop the search after finding this many matches.
--- Use `math.huge` to place no limit on the number of matches.
--- (default: `1`)
--- @field limit number
--- Find files or directories (or other items as specified by `opts.type`) in the given path.
@ -194,23 +212,10 @@ end
--- - path: full path of the current item
--- The function should return `true` if the given item is considered a match.
---
---@param opts (table) Optional keyword arguments:
--- - path (string): Path to begin searching from. If
--- omitted, the |current-directory| is used.
--- - upward (boolean, default false): If true, search
--- upward through parent directories. Otherwise,
--- search through child directories
--- (recursively).
--- - stop (string): Stop searching when this directory is
--- reached. The directory itself is not searched.
--- - type (string): Find only items of the given type.
--- If omitted, all items that match {names} are included.
--- - limit (number, default 1): Stop the search after
--- finding this many matches. Use `math.huge` to
--- place no limit on the number of matches.
---@param opts vim.fs.find.Opts Optional keyword arguments:
---@return (string[]) # Normalized paths |vim.fs.normalize()| of all matching items
function M.find(names, opts)
opts = opts or {} --[[@as vim.fs.find.opts]]
opts = opts or {}
vim.validate({
names = { names, { 's', 't', 'f' } },
path = { opts.path, 's', true },
@ -318,6 +323,13 @@ function M.find(names, opts)
return matches
end
--- @class vim.fs.normalize.Opts
--- @inlinedoc
---
--- Expand environment variables.
--- (default: `true`)
--- @field expand_env boolean
--- Normalize a path to a standard format. A tilde (~) character at the
--- beginning of the path is expanded to the user's home directory and any
--- backslash (\) characters are converted to forward slashes (/). Environment
@ -337,9 +349,8 @@ end
--- ```
---
---@param path (string) Path to normalize
---@param opts table|nil Options:
--- - expand_env: boolean Expand environment variables (default: true)
---@return (string) Normalized path
---@param opts? vim.fs.normalize.Opts
---@return (string) : Normalized path
function M.normalize(path, opts)
opts = opts or {}

View File

@ -64,11 +64,13 @@
--- In addition to the |vim.iter()| function, the |vim.iter| module provides
--- convenience functions like |vim.iter.filter()| and |vim.iter.totable()|.
---@nodoc
---@class IterMod
---@operator call:Iter
local M = {}
---@nodoc
---@class Iter
local Iter = {}
Iter.__index = Iter
@ -77,6 +79,7 @@ Iter.__call = function(self)
end
--- Special case implementations for iterators on list tables.
---@nodoc
---@class ListIter : Iter
---@field _table table Underlying table data
---@field _head number Index to the front of a table iterator

View File

@ -10,16 +10,37 @@ local M = {}
---@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: uv.aliases.fs_stat_types}
---@alias CacheEntry {hash:CacheHash, chunk:string}
---@class ModuleFindOpts
---@field all? boolean Search for all matches (defaults to `false`)
---@field rtp? boolean Search for modname in the runtime path (defaults to `true`)
---@field patterns? string[] Patterns to use (defaults to `{"/init.lua", ".lua"}`)
---@field paths? string[] Extra paths to search for modname
--- @class vim.loader.find.Opts
--- @inlinedoc
---
--- Search for modname in the runtime path.
--- (default: `true`)
--- @field rtp? boolean
---
--- Extra paths to search for modname
--- (default: `{}`)
--- @field paths? string[]
---
--- List of patterns to use when searching for modules.
--- A pattern is a string added to the basename of the Lua module being searched.
--- (default: `{"/init.lua", ".lua"}`)
--- @field patterns? string[]
---
--- Search for all matches.
--- (default: `false`)
--- @field all? boolean
---@class ModuleInfo
---@field modpath string Path of the module
---@field modname string Name of the module
---@field stat? uv.uv_fs_t File stat of the module path
--- @class vim.loader.ModuleInfo
--- @inlinedoc
---
--- Path of the module
--- @field modpath string
---
--- Name of the module
--- @field modname string
---
--- The fs_stat of the module path. Won't be returned for `modname="*"`
--- @field stat? uv.uv_fs_t
---@alias LoaderStats table<string, {total:number, time:number, [string]:number?}?>
@ -29,14 +50,14 @@ M.path = vim.fn.stdpath('cache') .. '/luac'
---@nodoc
M.enabled = false
---@class Loader
---@field _rtp string[]
---@field _rtp_pure string[]
---@field _rtp_key string
---@field _hashes? table<string, CacheHash>
---@class (private) Loader
---@field private _rtp string[]
---@field private _rtp_pure string[]
---@field private _rtp_key string
---@field private _hashes? table<string, CacheHash>
local Loader = {
VERSION = 4,
---@type table<string, table<string,ModuleInfo>>
---@type table<string, table<string,vim.loader.ModuleInfo>>
_indexed = {},
---@type table<string, string[]>
_topmods = {},
@ -270,17 +291,8 @@ end
--- Finds Lua modules for the given module name.
---@param modname string Module name, or `"*"` to find the top-level modules instead
---@param opts? ModuleFindOpts (table) Options for finding a module:
--- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`)
--- - paths: (string[]) Extra paths to search for modname (defaults to `{}`)
--- - patterns: (string[]) List of patterns to use when searching for modules.
--- A pattern is a string added to the basename of the Lua module being searched.
--- (defaults to `{"/init.lua", ".lua"}`)
--- - all: (boolean) Return all matches instead of just the first one (defaults to `false`)
---@return ModuleInfo[] (table) A list of results with the following properties:
--- - modpath: (string) the path to the module
--- - modname: (string) the name of the module
--- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"`
---@param opts? vim.loader.find.Opts Options for finding a module:
---@return vim.loader.ModuleInfo[]
function M.find(modname, opts)
opts = opts or {}
@ -306,7 +318,7 @@ function M.find(modname, opts)
patterns[p] = '/lua/' .. basename .. pattern
end
---@type ModuleInfo[]
---@type vim.loader.ModuleInfo[]
local results = {}
-- Only continue if we haven't found anything yet or we want to find all
@ -472,12 +484,12 @@ function Loader.track(stat, f)
end
end
---@class ProfileOpts
---@class (private) vim.loader._profile.Opts
---@field loaders? boolean Add profiling to the loaders
--- Debug function that wraps all loaders and tracks stats
---@private
---@param opts ProfileOpts?
---@param opts vim.loader._profile.Opts?
function M._profile(opts)
Loader.get_rtp = Loader.track('get_rtp', Loader.get_rtp)
Loader.read = Loader.track('read', Loader.read)

View File

@ -108,12 +108,12 @@ function lsp._buf_get_line_ending(bufnr)
end
-- Tracks all clients created via lsp.start_client
local active_clients = {} --- @type table<integer,lsp.Client>
local active_clients = {} --- @type table<integer,vim.lsp.Client>
local all_buffer_active_clients = {} --- @type table<integer,table<integer,true>>
local uninitialized_clients = {} --- @type table<integer,lsp.Client>
local uninitialized_clients = {} --- @type table<integer,vim.lsp.Client>
---@param bufnr? integer
---@param fn fun(client: lsp.Client, client_id: integer, bufnr: integer)
---@param fn fun(client: vim.lsp.Client, client_id: integer, bufnr: integer)
local function for_each_buffer_client(bufnr, fn, restrict_client_ids)
validate({
fn = { fn, 'f' },
@ -200,105 +200,15 @@ local function once(fn)
end
end
-- FIXME: DOC: Shouldn't need to use a dummy function
--
--- LSP client object. You can get an active client object via
--- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
--- @class vim.lsp.start.Opts
--- @inlinedoc
---
--- - Methods:
--- - request(method, params, [handler], bufnr)
--- Sends a request to the server.
--- This is a thin wrapper around {client.rpc.request} with some additional
--- checking.
--- If {handler} is not specified, If one is not found there, then an error will occur.
--- Returns: {status}, {[client_id]}. {status} is a boolean indicating if
--- the notification was successful. If it is `false`, then it will always
--- be `false` (the client has shutdown).
--- If {status} is `true`, the function returns {request_id} as the second
--- result. You can use this with `client.cancel_request(request_id)`
--- to cancel the request.
--- Predicate used to decide if a client should be re-used. Used on all
--- running clients. The default implementation re-uses a client if name and
--- root_dir matches.
--- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean
---
--- - request_sync(method, params, timeout_ms, bufnr)
--- Sends a request to the server and synchronously waits for the response.
--- This is a wrapper around {client.request}
--- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from
--- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a
--- string describing the failure reason. If the request was unsuccessful returns `nil`.
---
--- - notify(method, params)
--- Sends a notification to an LSP server.
--- Returns: a boolean to indicate if the notification was successful. If
--- it is false, then it will always be false (the client has shutdown).
---
--- - cancel_request(id)
--- Cancels a request with a given request id.
--- Returns: same as `notify()`.
---
--- - stop([force])
--- Stops a client, optionally with force.
--- By default, it will just ask the server to shutdown without force.
--- If you request to stop a client which has previously been requested to
--- shutdown, it will automatically escalate and force shutdown.
---
--- - is_stopped()
--- Checks whether a client is stopped.
--- Returns: true if the client is fully stopped.
---
--- - on_attach(client, bufnr)
--- Runs the on_attach function from the client's config if it was defined.
--- Useful for buffer-local setup.
---
--- - supports_method(method, [opts]): boolean
--- Checks if a client supports a given method.
--- Always returns true for unknown off-spec methods.
--- [opts] is a optional `{bufnr?: integer}` table.
--- Some language server capabilities can be file specific.
---
--- - Members
--- - {id} (number): The id allocated to the client.
---
--- - {name} (string): If a name is specified on creation, that will be
--- used. Otherwise it is just the client id. This is used for
--- logs and messages.
---
--- - {rpc} (table): RPC client object, for low level interaction with the
--- client. See |vim.lsp.rpc.start()|.
---
--- - {offset_encoding} (string): The encoding used for communicating
--- with the server. You can modify this in the `config`'s `on_init` method
--- before text is sent to the server.
---
--- - {handlers} (table): The handlers used by the client as described in |lsp-handler|.
---
--- - {commands} (table): Table of command name to function which is called if
--- any LSP action (code action, code lenses, ...) triggers the command.
--- Client commands take precedence over the global command registry.
---
--- - {requests} (table): The current pending requests in flight
--- to the server. Entries are key-value pairs with the key
--- being the request ID while the value is a table with `type`,
--- `bufnr`, and `method` key-value pairs. `type` is either "pending"
--- for an active request, or "cancel" for a cancel request. It will
--- be "complete" ephemerally while executing |LspRequest| autocmds
--- when replies are received from the server.
---
--- - {config} (table): Reference of the table that was passed by the user
--- to |vim.lsp.start_client()|.
---
--- - {server_capabilities} (table): Response from the server sent on
--- `initialize` describing the server's capabilities.
---
--- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages
--- sent by the server.
---
--- - {settings} Map with language server specific settings.
--- See {config} in |vim.lsp.start_client()|
---
--- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()|
lsp.client = nil
--- @class lsp.StartOpts
--- @field reuse_client fun(client: lsp.Client, config: table): boolean
--- Buffer handle to attach to if starting or re-using a client (0 for current).
--- @field bufnr integer
--- Create a new LSP client and start a language server or reuses an already
@ -337,17 +247,9 @@ lsp.client = nil
--- Either use |:au|, |nvim_create_autocmd()| or put the call in a
--- `ftplugin/<filetype_name>.lua` (See |ftplugin-name|)
---
---@param config lsp.ClientConfig Same configuration as documented in |vim.lsp.start_client()|
---@param opts lsp.StartOpts? Optional keyword arguments:
--- - reuse_client (fun(client: client, config: table): boolean)
--- Predicate used to decide if a client should be re-used.
--- Used on all running clients.
--- The default implementation re-uses a client if name
--- and root_dir matches.
--- - bufnr (number)
--- Buffer handle to attach to if starting or re-using a
--- client (0 for current).
---@return integer? client_id
--- @param config vim.lsp.ClientConfig Configuration for the server.
--- @param opts vim.lsp.start.Opts? Optional keyword arguments
--- @return integer? client_id
function lsp.start(config, opts)
opts = opts or {}
local reuse_client = opts.reuse_client
@ -428,7 +330,7 @@ local function is_empty_or_default(bufnr, option)
end
---@private
---@param client lsp.Client
---@param client vim.lsp.Client
---@param bufnr integer
function lsp._set_defaults(client, bufnr)
if
@ -482,7 +384,7 @@ local function reset_defaults(bufnr)
end)
end
--- @param client lsp.Client
--- @param client vim.lsp.Client
local function on_client_init(client)
local id = client.id
uninitialized_clients[id] = nil
@ -552,121 +454,9 @@ local function on_client_exit(code, signal, client_id)
end)
end
-- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are
-- documented twice: Here, and on the methods themselves (e.g.
-- `client.request()`). This is a workaround for the vimdoc generator script
-- not handling method names correctly. If you change the documentation on
-- either, please make sure to update the other as well.
--
--- Starts and initializes a client with the given configuration.
---
--- Field `cmd` in {config} is required.
---
---@param config (lsp.ClientConfig) Configuration for the server:
--- - cmd: (string[]|fun(dispatchers: table):table) 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()|
---
--- - cmd_cwd: (string, default=|getcwd()|) Directory to launch
--- the `cmd` process. Not related to `root_dir`.
---
--- - cmd_env: (table) Environment flags to pass to the LSP on
--- spawn. Must be specified using a table.
--- Non-string values are coerced to string.
--- Example:
--- ```
--- { PORT = 8080; HOST = "0.0.0.0"; }
--- ```
---
--- - detached: (boolean, default true) 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.
---
--- - workspace_folders: (table) 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.
---
--- - capabilities: 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.
---
--- - handlers: Map of language server method names to |lsp-handler|
---
--- - settings: Map with language server specific settings. These are
--- returned to the language server if requested via `workspace/configuration`.
--- Keys are case-sensitive.
---
--- - commands: 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.
---
--- - init_options Values to pass in the initialization request
--- as `initializationOptions`. See `initialize` in the LSP spec.
---
--- - name: (string, default=client-id) Name in log messages.
---
--- - get_language_id: function(bufnr, filetype) -> language ID as string.
--- Defaults to the filetype.
---
--- - offset_encoding: (default="utf-16") One of "utf-8", "utf-16",
--- or "utf-32" which is the encoding that the LSP server expects. Client does
--- not verify this is correct.
---
--- - on_error: Callback with parameters (code, ...), 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.
---
--- - before_init: Callback with parameters (initialize_params, config)
--- 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.
---
--- - on_init: Callback (client, initialize_result) 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.
---
--- - on_exit Callback (code, signal, client_id) invoked on client
--- exit.
--- - code: exit code of the process
--- - signal: number describing the signal used to terminate (if any)
--- - client_id: client handle
---
--- - on_attach: Callback (client, bufnr) invoked when client
--- attaches to a buffer.
---
--- - trace: ("off" | "messages" | "verbose" | nil) passed directly to the language
--- server in the initialize request. Invalid/empty values will default to "off"
---
--- - flags: 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.
---
--- - root_dir: (string) Directory where the LSP
--- server will base its workspaceFolders, rootUri, and rootPath
--- on initialization.
---
---@return integer|nil client_id. |vim.lsp.get_client_by_id()| Note: client may not be
--- @param config vim.lsp.ClientConfig Configuration for the server.
--- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once
--- the client has been initialized.
function lsp.start_client(config)
@ -927,7 +717,7 @@ end
---
---@param client_id integer client id
---
---@return (nil|lsp.Client) client rpc object
---@return (nil|vim.lsp.Client) client rpc object
function lsp.get_client_by_id(client_id)
return active_clients[client_id] or uninitialized_clients[client_id]
end
@ -943,7 +733,7 @@ end
--- Stops a client(s).
---
--- You can also use the `stop()` function on a |vim.lsp.client| object.
--- You can also use the `stop()` function on a |vim.lsp.Client| object.
--- To stop all clients:
---
--- ```lua
@ -953,7 +743,7 @@ end
--- By default asks the server to shutdown, unless stop was requested
--- already for this client, then force-shutdown is attempted.
---
---@param client_id integer|table id or |vim.lsp.client| object, or list thereof
---@param client_id integer|vim.lsp.Client id or |vim.lsp.Client| object, or list thereof
---@param force boolean|nil shutdown forcefully
function lsp.stop_client(client_id, force)
local ids = type(client_id) == 'table' and client_id or { client_id }
@ -968,28 +758,32 @@ function lsp.stop_client(client_id, force)
end
end
---@class vim.lsp.get_clients.filter
---@field id integer|nil Match clients by id
---@field bufnr integer|nil match clients attached to the given buffer
---@field name string|nil match clients by name
---@field method string|nil match client by supported method name
--- Key-value pairs used to filter the returned clients.
--- @class vim.lsp.get_clients.Filter
--- @inlinedoc
---
--- Only return clients with the given id
--- @field id? integer
---
--- Only return clients attached to this buffer
--- @field bufnr? integer
---
--- Only return clients with the given name
--- @field name? string
---
--- Only return clients supporting the given method
--- @field method? string
--- Get active clients.
---
---@param filter vim.lsp.get_clients.filter|nil (table|nil) A table with
--- key-value pairs used to filter the returned clients.
--- The available keys are:
--- - id (number): Only return clients with the given id
--- - bufnr (number): Only return clients attached to this buffer
--- - name (string): Only return clients with the given name
--- - method (string): Only return clients supporting the given method
---@return lsp.Client[]: List of |vim.lsp.client| objects
---@param filter? vim.lsp.get_clients.Filter
---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects
function lsp.get_clients(filter)
validate({ filter = { filter, 't', true } })
filter = filter or {}
local clients = {} --- @type lsp.Client[]
local clients = {} --- @type vim.lsp.Client[]
local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {})
or active_clients
@ -1233,15 +1027,20 @@ function lsp.omnifunc(findstart, base)
return vim.lsp._completion.omnifunc(findstart, base)
end
--- @class vim.lsp.formatexpr.Opts
--- @inlinedoc
---
--- The timeout period for the formatting request.
--- (default: 500ms).
--- @field timeout_ms integer
--- Provides an interface between the built-in client and a `formatexpr` function.
---
--- Currently only supports a single client. This can be set via
--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
--- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
---
---@param opts table options for customizing the formatting expression which takes the
--- following optional keys:
--- * timeout_ms (default 500ms). The timeout period for the formatting request.
---@param opts? vim.lsp.formatexpr.Opts
function lsp.formatexpr(opts)
opts = opts or {}
local timeout_ms = opts.timeout_ms or 500
@ -1313,14 +1112,14 @@ function lsp.client_is_stopped(client_id)
end
--- Gets a map of client_id:client pairs for the given buffer, where each value
--- is a |vim.lsp.client| object.
--- is a |vim.lsp.Client| object.
---
---@param bufnr (integer|nil): Buffer handle, or 0 for current
---@return table result is table of (client_id, client) pairs
---@deprecated Use |vim.lsp.get_clients()| instead.
function lsp.buf_get_clients(bufnr)
vim.deprecate('vim.lsp.buf_get_clients()', 'vim.lsp.get_clients()', '0.12')
local result = {} --- @type table<integer,lsp.Client>
local result = {} --- @type table<integer,vim.lsp.Client>
for _, client in ipairs(lsp.get_clients({ bufnr = resolve_bufnr(bufnr) })) do
result[client.id] = client
end

View File

@ -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)

View File

@ -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
---
---@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.
--- 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
---
--- 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' },

View File

@ -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)
--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
--- @class 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)

View File

@ -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)

View File

@ -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 = {}

View File

@ -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

View File

@ -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 {}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -108,22 +108,25 @@ function M.read(path)
return contents
end
---@class vim.trust.opts
---@field action string
---@field path? string
---@field bufnr? integer
--- @class vim.trust.opts
--- @inlinedoc
---
--- - `'allow'` to add a file to the trust database and trust it,
--- - `'deny'` to add a file to the trust database and deny it,
--- - `'remove'` to remove file from the trust database
--- @field action 'allow'|'deny'|'remove'
---
--- Path to a file to update. Mutually exclusive with {bufnr}.
--- Cannot be used when {action} is "allow".
--- @field path? string
--- Buffer number to update. Mutually exclusive with {path}.
--- @field bufnr? integer
--- Manage the trust database.
---
--- The trust database is located at |$XDG_STATE_HOME|/nvim/trust.
---
---@param opts (table):
--- - action (string): "allow" to add a file to the trust database and trust it,
--- "deny" to add a file to the trust database and deny it,
--- "remove" to remove file from the trust database
--- - path (string|nil): Path to a file to update. Mutually exclusive with {bufnr}.
--- Cannot be used when {action} is "allow".
--- - bufnr (number|nil): Buffer number to update. Mutually exclusive with {path}.
---@param opts? vim.trust.opts
---@return boolean success true if operation was successful
---@return string msg full path if operation was successful, else error message
function M.trust(opts)

View File

@ -65,8 +65,13 @@ function vim.deepcopy(orig, noref)
end
--- @class vim.gsplit.Opts
--- @field plain? boolean Use `sep` literally (as in string.find).
--- @field trimempty? boolean Discard empty segments at start and end of the sequence.
--- @inlinedoc
---
--- Use `sep` literally (as in string.find).
--- @field plain? boolean
---
--- Discard empty segments at start and end of the sequence.
--- @field trimempty? boolean
--- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion
--- (as opposed to |vim.split()| which is "eager").
@ -96,10 +101,8 @@ end
---
--- @param s string String to split
--- @param sep string Separator or pattern
--- @param opts? vim.gsplit.Opts (table) Keyword arguments |kwargs|:
--- - plain: (boolean) Use `sep` literally (as in string.find).
--- - trimempty: (boolean) Discard empty segments at start and end of the sequence.
---@return fun():string|nil (function) Iterator over the split components
--- @param opts? vim.gsplit.Opts Keyword arguments |kwargs|:
--- @return fun():string|nil (function) Iterator over the split components
function vim.gsplit(s, sep, opts)
local plain --- @type boolean?
local trimempty = false
@ -192,7 +195,7 @@ end
---
---@param s string String to split
---@param sep string Separator or pattern
---@param opts? table Keyword arguments |kwargs| accepted by |vim.gsplit()|
---@param opts? vim.gsplit.Opts Keyword arguments |kwargs|:
---@return string[] : List of split components
function vim.split(s, sep, opts)
local t = {}
@ -276,6 +279,9 @@ function vim.tbl_filter(func, t)
end
--- @class vim.tbl_contains.Opts
--- @inlinedoc
---
--- `value` is a function reference to be checked (default false)
--- @field predicate? boolean
--- Checks if a table contains a given value, specified either directly or via
@ -294,8 +300,7 @@ end
---
---@param t table Table to check
---@param value any Value to compare or predicate function reference
---@param opts? vim.tbl_contains.Opts (table) Keyword arguments |kwargs|:
--- - predicate: (boolean) `value` is a function reference to be checked (default false)
---@param opts? vim.tbl_contains.Opts Keyword arguments |kwargs|:
---@return boolean `true` if `t` contains `value`
function vim.tbl_contains(t, value, opts)
vim.validate({ t = { t, 't' }, opts = { opts, 't', true } })
@ -764,6 +769,7 @@ do
['userdata'] = 'userdata',
}
--- @nodoc
--- @class vim.validate.Spec {[1]: any, [2]: string|string[], [3]: boolean }
--- @field [1] any Argument value
--- @field [2] string|string[]|fun(v:any):boolean, string? Type name, or callable

View File

@ -101,7 +101,7 @@ local function get_extmark_range(bufnr, extmark_id)
return { mark[1], mark[2], mark[3].end_row, mark[3].end_col }
end
--- @class vim.snippet.Tabstop
--- @class (private) vim.snippet.Tabstop
--- @field extmark_id integer
--- @field bufnr integer
--- @field index integer
@ -177,7 +177,7 @@ function Tabstop:set_right_gravity(right_gravity)
})
end
--- @class vim.snippet.Session
--- @class (private) vim.snippet.Session
--- @field bufnr integer
--- @field extmark_id integer
--- @field tabstops table<integer, vim.snippet.Tabstop[]>

View File

@ -1,6 +1,6 @@
local api = vim.api
---@type table<integer,LanguageTree>
---@type table<integer,vim.treesitter.LanguageTree>
local parsers = setmetatable({}, { __mode = 'v' })
local M = vim._defer_require('vim.treesitter', {
@ -30,7 +30,7 @@ M.minimum_language_version = vim._ts_get_minimum_language_version()
---@param lang string Language of the parser
---@param opts (table|nil) Options to pass to the created language tree
---
---@return LanguageTree object to use for parsing
---@return vim.treesitter.LanguageTree object to use for parsing
function M._create_parser(bufnr, lang, opts)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
@ -80,7 +80,7 @@ end
---@param lang (string|nil) Filetype of this parser (default: buffer filetype)
---@param opts (table|nil) Options to pass to the created language tree
---
---@return LanguageTree object to use for parsing
---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_parser(bufnr, lang, opts)
opts = opts or {}
@ -119,7 +119,7 @@ end
---@param lang string Language of this string
---@param opts (table|nil) Options to pass to the created language tree
---
---@return LanguageTree object to use for parsing
---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_string_parser(str, lang, opts)
vim.validate({
str = { str, 'string' },
@ -172,7 +172,7 @@ end
---to get the range with directives applied.
---@param node TSNode
---@param source integer|string|nil Buffer or string from which the {node} is extracted
---@param metadata TSMetadata|nil
---@param metadata vim.treesitter.query.TSMetadata|nil
---@return Range6
function M.get_range(node, source, metadata)
if metadata and metadata.range then
@ -326,10 +326,21 @@ function M.get_captures_at_cursor(winnr)
return captures
end
--- @class vim.treesitter.GetNodeOpts
--- Optional keyword arguments:
--- @class vim.treesitter.get_node.Opts
--- @inlinedoc
---
--- Buffer number (nil or 0 for current buffer)
--- @field bufnr integer?
---
--- 0-indexed (row, col) tuple. Defaults to cursor position in the
--- current window. Required if {bufnr} is not the current buffer
--- @field pos { [1]: integer, [2]: integer }?
---
--- Parser language. (default: from buffer filetype)
--- @field lang string?
---
--- Ignore injected languages (default true)
--- @field ignore_injections boolean?
--- Returns the smallest named node at the given position
@ -342,12 +353,7 @@ end
--- vim.treesitter.get_parser(bufnr):parse(range)
--- ```
---
---@param opts vim.treesitter.GetNodeOpts? Optional keyword arguments:
--- - bufnr integer|nil Buffer number (nil or 0 for current buffer)
--- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the
--- current window. Required if {bufnr} is not the current buffer
--- - lang string|nil Parser language. (default: from buffer filetype)
--- - ignore_injections boolean Ignore injected languages (default true)
---@param opts vim.treesitter.get_node.Opts?
---
---@return TSNode | nil Node at the given position
function M.get_node(opts)

View File

@ -45,7 +45,7 @@ local function guess_query_lang(buf)
end
--- @param buf integer
--- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil
--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil
--- @return QueryLinterNormalizedOpts
local function normalize_opts(buf, opts)
opts = opts or {}
@ -122,7 +122,7 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang)
end)
--- @param buf integer
--- @param match TSMatch
--- @param match vim.treesitter.query.TSMatch
--- @param query Query
--- @param lang_context QueryLinterLanguageContext
--- @param diagnostics Diagnostic[]
@ -153,7 +153,7 @@ end
--- @private
--- @param buf integer Buffer to lint
--- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting
--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil Options for linting
function M.lint(buf, opts)
if buf == 0 then
buf = api.nvim_get_current_buf()

View File

@ -1,23 +1,21 @@
local api = vim.api
---@class TSDevModule
local M = {}
---@private
---@class TSTreeView
---@class (private) vim.treesitter.dev.TSTreeView
---@field ns integer API namespace
---@field opts TSTreeViewOpts
---@field nodes TSP.Node[]
---@field named TSP.Node[]
---@field opts vim.treesitter.dev.TSTreeViewOpts
---@field nodes vim.treesitter.dev.Node[]
---@field named vim.treesitter.dev.Node[]
local TSTreeView = {}
---@private
---@class TSTreeViewOpts
---@class (private) vim.treesitter.dev.TSTreeViewOpts
---@field anon boolean If true, display anonymous nodes.
---@field lang boolean If true, display the language alongside each node.
---@field indent number Number of spaces to indent nested lines.
---@class TSP.Node
---@class (private) vim.treesitter.dev.Node
---@field node TSNode Treesitter node
---@field field string? Node field
---@field depth integer Depth of this node in the tree
@ -25,7 +23,7 @@ local TSTreeView = {}
--- inspector is drawn.
---@field lang string Source language of this node
---@class TSP.Injection
---@class (private) vim.treesitter.dev.Injection
---@field lang string Source language of this injection
---@field root TSNode Root node of the injection
@ -45,9 +43,9 @@ local TSTreeView = {}
---@param depth integer Current recursion depth
---@param field string|nil The field of the current node
---@param lang string Language of the tree currently being traversed
---@param injections table<string, TSP.Injection> Mapping of node ids to root nodes
---@param injections table<string, vim.treesitter.dev.Injection> Mapping of node ids to root nodes
--- of injected language trees (see explanation above)
---@param tree TSP.Node[] Output table containing a list of tables each representing a node in the tree
---@param tree vim.treesitter.dev.Node[] Output table containing a list of tables each representing a node in the tree
local function traverse(node, depth, field, lang, injections, tree)
table.insert(tree, {
node = node,
@ -73,7 +71,7 @@ end
---@param bufnr integer Source buffer number
---@param lang string|nil Language of source buffer
---
---@return TSTreeView|nil
---@return vim.treesitter.dev.TSTreeView|nil
---@return string|nil Error message, if any
---
---@package
@ -88,7 +86,7 @@ function TSTreeView:new(bufnr, lang)
-- the primary tree that contains that root. Add a mapping from the node in the primary tree to
-- the root in the child tree to the {injections} table.
local root = parser:parse(true)[1]:root()
local injections = {} ---@type table<string, TSP.Injection>
local injections = {} ---@type table<string, vim.treesitter.dev.Injection>
parser:for_each_tree(function(parent_tree, parent_ltree)
local parent = parent_tree:root()
@ -109,7 +107,7 @@ function TSTreeView:new(bufnr, lang)
local nodes = traverse(root, 0, nil, parser:lang(), injections, {})
local named = {} ---@type TSP.Node[]
local named = {} ---@type vim.treesitter.dev.Node[]
for _, v in ipairs(nodes) do
if v.node:named() then
named[#named + 1] = v
@ -120,7 +118,7 @@ function TSTreeView:new(bufnr, lang)
ns = api.nvim_create_namespace('treesitter/dev-inspect'),
nodes = nodes,
named = named,
---@type TSTreeViewOpts
---@type vim.treesitter.dev.TSTreeViewOpts
opts = {
anon = false,
lang = false,
@ -171,7 +169,7 @@ end
--- Updates the cursor position in the inspector to match the node under the cursor.
---
--- @param treeview TSTreeView
--- @param treeview vim.treesitter.dev.TSTreeView
--- @param lang string
--- @param source_buf integer
--- @param inspect_buf integer
@ -278,7 +276,7 @@ end
--- The node number is dependent on whether or not anonymous nodes are displayed.
---
---@param i integer Node number to get
---@return TSP.Node
---@return vim.treesitter.dev.Node
---@package
function TSTreeView:get(i)
local t = self.opts.anon and self.nodes or self.named
@ -287,7 +285,7 @@ end
--- Iterate over all of the nodes in this View.
---
---@return (fun(): integer, TSP.Node) Iterator over all nodes in this View
---@return (fun(): integer, vim.treesitter.dev.Node) Iterator over all nodes in this View
---@return table
---@return integer
---@package
@ -295,22 +293,31 @@ function TSTreeView:iter()
return ipairs(self.opts.anon and self.nodes or self.named)
end
--- @class InspectTreeOpts
--- @field lang string? The language of the source buffer. If omitted, the
--- filetype of the source buffer is used.
--- @field bufnr integer? Buffer to draw the tree into. If omitted, a new
--- buffer is created.
--- @field winid integer? Window id to display the tree buffer in. If omitted,
--- a new window is created with {command}.
--- @field command string? Vimscript command to create the window. Default
--- value is "60vnew". Only used when {winid} is nil.
--- @field title (string|fun(bufnr:integer):string|nil) Title of the window. If a
--- function, it accepts the buffer number of the source
--- buffer as its only argument and should return a string.
--- @class vim.treesitter.dev.inspect_tree.Opts
--- @inlinedoc
---
--- The language of the source buffer. If omitted, the filetype of the source
--- buffer is used.
--- @field lang string?
---
--- Buffer to draw the tree into. If omitted, a new buffer is created.
--- @field bufnr integer?
---
--- Window id to display the tree buffer in. If omitted, a new window is
--- created with {command}.
--- @field winid integer?
---
--- Vimscript command to create the window. Default value is "60vnew".
--- Only used when {winid} is nil.
--- @field command string?
---
--- Title of the window. If a function, it accepts the buffer number of the
--- source buffer as its only argument and should return a string.
--- @field title (string|fun(bufnr:integer):string|nil)
--- @private
---
--- @param opts InspectTreeOpts?
--- @param opts vim.treesitter.dev.inspect_tree.Opts?
function M.inspect_tree(opts)
vim.validate({
opts = { opts, 't', true },

View File

@ -4,9 +4,9 @@ local Range = require('vim.treesitter._range')
local ns = api.nvim_create_namespace('treesitter/highlighter')
---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, TSMetadata
---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata
---@class vim.treesitter.highlighter.Query
---@class (private) vim.treesitter.highlighter.Query
---@field private _query vim.treesitter.Query?
---@field private lang string
---@field private hl_cache table<integer,integer>
@ -52,22 +52,23 @@ function TSHighlighterQuery:query()
return self._query
end
---@class vim.treesitter.highlighter.State
---@class (private) vim.treesitter.highlighter.State
---@field tstree TSTree
---@field next_row integer
---@field iter vim.treesitter.highlighter.Iter?
---@field highlighter_query vim.treesitter.highlighter.Query
---@nodoc
---@class vim.treesitter.highlighter
---@field active table<integer,vim.treesitter.highlighter>
---@field bufnr integer
---@field orig_spelloptions string
---@field private orig_spelloptions string
--- A map of highlight states.
--- This state is kept during rendering across each line update.
---@field _highlight_states vim.treesitter.highlighter.State[]
---@field _queries table<string,vim.treesitter.highlighter.Query>
---@field tree LanguageTree
---@field redraw_count integer
---@field private _highlight_states vim.treesitter.highlighter.State[]
---@field private _queries table<string,vim.treesitter.highlighter.Query>
---@field tree vim.treesitter.LanguageTree
---@field private redraw_count integer
local TSHighlighter = {
active = {},
}
@ -78,7 +79,7 @@ TSHighlighter.__index = TSHighlighter
---
--- Creates a highlighter for `tree`.
---
---@param tree LanguageTree parser object to use for highlighting
---@param tree vim.treesitter.LanguageTree parser object to use for highlighting
---@param opts (table|nil) Configuration of the highlighter:
--- - queries table overwrite queries used by the highlighter
---@return vim.treesitter.highlighter Created highlighter object

View File

@ -56,10 +56,17 @@ function M.require_language(lang, path, silent, symbol_name)
return true
end
---@class vim.treesitter.language.RequireLangOpts
---@field path? string
---@field silent? boolean
---@class vim.treesitter.language.add.Opts
---@inlinedoc
---
---Default filetype the parser should be associated with.
---(Default: {lang})
---@field filetype? string|string[]
---
---Optional path the parser is located at
---@field path? string
---
---Internal symbol name for the language to load
---@field symbol_name? string
--- Load parser with name {lang}
@ -67,13 +74,8 @@ end
--- Parsers are searched in the `parser` runtime directory, or the provided {path}
---
---@param lang string Name of the parser (alphanumerical and `_` only)
---@param opts (table|nil) Options:
--- - filetype (string|string[]) Default filetype the parser should be associated with.
--- Defaults to {lang}.
--- - path (string|nil) Optional path the parser is located at
--- - symbol_name (string|nil) Internal symbol name for the language to load
---@param opts? vim.treesitter.language.add.Opts Options:
function M.add(lang, opts)
---@cast opts vim.treesitter.language.RequireLangOpts
opts = opts or {}
local path = opts.path
local filetype = opts.filetype or lang

View File

@ -67,10 +67,11 @@ local TSCallbackNames = {
on_child_removed = 'child_removed',
}
---@class LanguageTree
---@nodoc
---@class vim.treesitter.LanguageTree
---@field private _callbacks table<TSCallbackName,function[]> Callback handlers
---@field package _callbacks_rec table<TSCallbackName,function[]> Callback handlers (recursive)
---@field private _children table<string,LanguageTree> Injected languages
---@field private _children table<string,vim.treesitter.LanguageTree> Injected languages
---@field private _injection_query Query Queries defining injected languages
---@field private _injections_processed boolean
---@field private _opts table Options
@ -89,7 +90,9 @@ local TSCallbackNames = {
---@field private _logfile? file*
local LanguageTree = {}
---@class LanguageTreeOpts
---Optional arguments:
---@class vim.treesitter.LanguageTree.new.Opts
---@inlinedoc
---@field queries table<string,string> -- Deprecated
---@field injections table<string,string>
@ -102,14 +105,11 @@ LanguageTree.__index = LanguageTree
---
---@param source (integer|string) Buffer or text string to parse
---@param lang string Root language of this tree
---@param opts (table|nil) Optional arguments:
--- - injections table Map of language to injection query strings. Overrides the
--- built-in runtime file searching for language injections.
---@param opts vim.treesitter.LanguageTree.new.Opts?
---@param parent_lang? string Parent language name of this tree
---@return LanguageTree parser object
---@return vim.treesitter.LanguageTree parser object
function LanguageTree.new(source, lang, opts, parent_lang)
language.add(lang)
---@type LanguageTreeOpts
opts = opts or {}
if source == 0 then
@ -118,7 +118,7 @@ function LanguageTree.new(source, lang, opts, parent_lang)
local injections = opts.injections or {}
--- @type LanguageTree
--- @type vim.treesitter.LanguageTree
local self = {
_source = source,
_lang = lang,
@ -194,7 +194,7 @@ local function tcall(f, ...)
end
---@private
---@vararg any
---@param ... any
function LanguageTree:_log(...)
if not self._logger then
return
@ -464,7 +464,7 @@ end
--- add recursion yourself if needed.
--- Invokes the callback for each |LanguageTree| and its children recursively
---
---@param fn fun(tree: LanguageTree, lang: string)
---@param fn fun(tree: vim.treesitter.LanguageTree, lang: string)
---@param include_self boolean|nil Whether to include the invoking tree in the results
function LanguageTree:for_each_child(fn, include_self)
vim.deprecate('LanguageTree:for_each_child()', 'LanguageTree:children()', '0.11')
@ -481,7 +481,7 @@ end
---
--- Note: This includes the invoking tree's child trees as well.
---
---@param fn fun(tree: TSTree, ltree: LanguageTree)
---@param fn fun(tree: TSTree, ltree: vim.treesitter.LanguageTree)
function LanguageTree:for_each_tree(fn)
for _, tree in pairs(self._trees) do
fn(tree, self)
@ -498,7 +498,7 @@ end
---
---@private
---@param lang string Language to add.
---@return LanguageTree injected
---@return vim.treesitter.LanguageTree injected
function LanguageTree:add_child(lang)
if self._children[lang] then
self:remove_child(lang)
@ -668,7 +668,7 @@ end
---@param node TSNode
---@param source string|integer
---@param metadata TSMetadata
---@param metadata vim.treesitter.query.TSMetadata
---@param include_children boolean
---@return Range6[]
local function get_node_ranges(node, source, metadata, include_children)
@ -702,13 +702,14 @@ local function get_node_ranges(node, source, metadata, include_children)
return ranges
end
---@class TSInjectionElem
---@nodoc
---@class vim.treesitter.languagetree.InjectionElem
---@field combined boolean
---@field regions Range6[][]
---@alias TSInjection table<string,table<integer,TSInjectionElem>>
---@alias vim.treesitter.languagetree.Injection table<string,table<integer,vim.treesitter.languagetree.InjectionElem>>
---@param t table<integer,TSInjection>
---@param t table<integer,vim.treesitter.languagetree.Injection>
---@param tree_index integer
---@param pattern integer
---@param lang string
@ -783,7 +784,7 @@ end
--- Extract injections according to:
--- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection
---@param match table<integer,TSNode[]>
---@param metadata TSMetadata
---@param metadata vim.treesitter.query.TSMetadata
---@return string?, boolean, Range6[]
function LanguageTree:_get_injection(match, metadata)
local ranges = {} ---@type Range6[]
@ -836,7 +837,7 @@ function LanguageTree:_get_injections()
return {}
end
---@type table<integer,TSInjection>
---@type table<integer,vim.treesitter.languagetree.Injection>
local injections = {}
for index, tree in pairs(self._trees) do
@ -1150,7 +1151,7 @@ end
--- Gets the appropriate language that contains {range}.
---
---@param range Range4 `{ start_line, start_col, end_line, end_col }`
---@return LanguageTree Managing {range}
---@return vim.treesitter.LanguageTree Managing {range}
function LanguageTree:language_for_range(range)
for _, child in pairs(self._children) do
if child:contains(range) then

View File

@ -3,6 +3,7 @@ local language = require('vim.treesitter.language')
local M = {}
---@nodoc
---Parsed query, see |vim.treesitter.query.parse()|
---
---@class vim.treesitter.Query
@ -31,6 +32,7 @@ function Query.new(lang, ts_query)
return self
end
---@nodoc
---Information for Query, see |vim.treesitter.query.parse()|
---@class vim.treesitter.QueryInfo
---
@ -296,7 +298,7 @@ end
--- handling the "any" vs "all" semantics. They are called from the
--- predicate_handlers table with the appropriate arguments for each predicate.
local impl = {
--- @param match TSMatch
--- @param match vim.treesitter.query.TSMatch
--- @param source integer|string
--- @param predicate any[]
--- @param any boolean
@ -331,7 +333,7 @@ local impl = {
return not any
end,
--- @param match TSMatch
--- @param match vim.treesitter.query.TSMatch
--- @param source integer|string
--- @param predicate any[]
--- @param any boolean
@ -371,7 +373,7 @@ local impl = {
end,
})
--- @param match TSMatch
--- @param match vim.treesitter.query.TSMatch
--- @param source integer|string
--- @param predicate any[]
--- @param any boolean
@ -394,7 +396,7 @@ local impl = {
end
end)(),
--- @param match TSMatch
--- @param match vim.treesitter.query.TSMatch
--- @param source integer|string
--- @param predicate any[]
--- @param any boolean
@ -421,12 +423,13 @@ local impl = {
end,
}
---@class TSMatch
---@nodoc
---@class vim.treesitter.query.TSMatch
---@field pattern? integer
---@field active? boolean
---@field [integer] TSNode[]
---@alias TSPredicate fun(match: TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean
---@alias TSPredicate fun(match: vim.treesitter.query.TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean
-- Predicate handler receive the following arguments
-- (match, pattern, bufnr, predicate)
@ -534,13 +537,14 @@ local predicate_handlers = {
predicate_handlers['vim-match?'] = predicate_handlers['match?']
predicate_handlers['any-vim-match?'] = predicate_handlers['any-match?']
---@class TSMetadata
---@nodoc
---@class vim.treesitter.query.TSMetadata
---@field range? Range
---@field conceal? string
---@field [integer] TSMetadata
---@field [integer] vim.treesitter.query.TSMetadata
---@field [string] integer|string
---@alias TSDirective fun(match: TSMatch, _, _, predicate: (string|integer)[], metadata: TSMetadata)
---@alias TSDirective fun(match: vim.treesitter.query.TSMatch, _, _, predicate: (string|integer)[], metadata: vim.treesitter.query.TSMetadata)
-- Predicate handler receive the following arguments
-- (match, pattern, bufnr, predicate)
@ -767,7 +771,7 @@ local function is_directive(name)
end
---@private
---@param match TSMatch
---@param match vim.treesitter.query.TSMatch
---@param pattern integer
---@param source integer|string
function Query:match_preds(match, pattern, source)
@ -806,8 +810,8 @@ function Query:match_preds(match, pattern, source)
end
---@private
---@param match TSMatch
---@param metadata TSMetadata
---@param match vim.treesitter.query.TSMatch
---@param metadata vim.treesitter.query.TSMetadata
function Query:apply_directives(match, pattern, source, metadata)
local preds = self.info.patterns[pattern]
@ -871,7 +875,7 @@ end
---@param start? integer Starting line for the search. Defaults to `node:start()`.
---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`.
---
---@return (fun(end_line: integer|nil): integer, TSNode, TSMetadata):
---@return (fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata):
--- capture id, capture node, metadata
function Query:iter_captures(node, source, start, stop)
if type(source) == 'number' and source == 0 then
@ -880,7 +884,7 @@ function Query:iter_captures(node, source, start, stop)
start, stop = value_or_node_range(start, stop, node)
local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, TSMatch
local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, vim.treesitter.query.TSMatch
local function iter(end_line)
local capture, captured_node, match = raw_iter()
local metadata = {}
@ -952,7 +956,7 @@ function Query:iter_matches(node, source, start, stop, opts)
start, stop = value_or_node_range(start, stop, node)
local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, TSMatch
local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, vim.treesitter.query.TSMatch
local function iter()
local pattern, match = raw_iter()
local metadata = {}
@ -982,9 +986,16 @@ function Query:iter_matches(node, source, start, stop, opts)
return iter
end
---@class QueryLinterOpts
---@field langs (string|string[]|nil)
---@field clear (boolean)
--- Optional keyword arguments:
--- @class vim.treesitter.query.lint.Opts
--- @inlinedoc
---
--- Language(s) to use for checking the query.
--- If multiple languages are specified, queries are validated for all of them
--- @field langs? string|string[]
---
--- Just clear current lint errors
--- @field clear boolean
--- Lint treesitter queries using installed parser, or clear lint errors.
---
@ -999,10 +1010,7 @@ end
--- of the query file, e.g., if the path ends in `/lua/highlights.scm`, the parser for the
--- `lua` language will be used.
---@param buf (integer) Buffer handle
---@param opts? QueryLinterOpts (table) Optional keyword arguments:
--- - langs (string|string[]|nil) Language(s) to use for checking the query.
--- If multiple languages are specified, queries are validated for all of them
--- - clear (boolean) if `true`, just clear current lint errors
---@param opts? vim.treesitter.query.lint.Opts
function M.lint(buf, opts)
if opts and opts.clear then
vim.treesitter._query_linter.clear(buf)

View File

@ -54,7 +54,8 @@
local M = {}
---@class Version
---@nodoc
---@class vim.Version
---@field [1] number
---@field [2] number
---@field [3] number
@ -111,7 +112,7 @@ function Version:__newindex(key, value)
end
end
---@param other Version
---@param other vim.Version
function Version:__eq(other)
for i = 1, 3 do
if self[i] ~= other[i] then
@ -132,7 +133,7 @@ function Version:__tostring()
return ret
end
---@param other Version
---@param other vim.Version
function Version:__lt(other)
for i = 1, 3 do
if self[i] > other[i] then
@ -144,7 +145,7 @@ function Version:__lt(other)
return -1 == cmp_prerel(self.prerelease, other.prerelease)
end
---@param other Version
---@param other vim.Version
function Version:__le(other)
return self < other or self == other
end
@ -153,9 +154,9 @@ end
---
--- Creates a new Version object, or returns `nil` if `version` is invalid.
---
--- @param version string|number[]|Version
--- @param version string|number[]|vim.Version
--- @param strict? boolean Reject "1.0", "0-x", "3.2a" or other non-conforming version strings
--- @return Version?
--- @return vim.Version?
function M._version(version, strict) -- Adapted from https://github.com/folke/lazy.nvim
if type(version) == 'table' then
if version.major then
@ -203,7 +204,7 @@ end
---TODO: generalize this, move to func.lua
---
---@generic T: Version
---@generic T: vim.Version
---@param versions T[]
---@return T?
function M.last(versions)
@ -216,14 +217,15 @@ function M.last(versions)
return last
end
---@class VersionRange
---@field from Version
---@field to? Version
---@class vim.VersionRange
---@inlinedoc
---@field from vim.Version
---@field to? vim.Version
local VersionRange = {}
--- @private
---
---@param version string|Version
---@param version string|vim.Version
function VersionRange:has(version)
if type(version) == 'string' then
---@diagnostic disable-next-line: cast-local-type
@ -272,6 +274,7 @@ end
--- @see # https://github.com/npm/node-semver#ranges
---
--- @param spec string Version range "spec"
--- @return vim.VersionRange
function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
if spec == '*' or spec == '' then
return setmetatable({ from = M.parse('0.0.0') }, { __index = VersionRange })
@ -300,8 +303,8 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
local semver = M.parse(version)
if semver then
local from = semver --- @type Version?
local to = vim.deepcopy(semver, true) --- @type Version?
local from = semver --- @type vim.Version?
local to = vim.deepcopy(semver, true) --- @type vim.Version?
---@diagnostic disable: need-check-nil
if mods == '' or mods == '=' then
to.patch = to.patch + 1
@ -340,7 +343,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
end
end
---@param v string|Version
---@param v string|vim.Version
---@return string
local function create_err_msg(v)
if type(v) == 'string' then
@ -369,8 +372,8 @@ end
---
--- @note Per semver, build metadata is ignored when comparing two otherwise-equivalent versions.
---
---@param v1 Version|number[]|string Version object.
---@param v2 Version|number[]|string Version to compare with `v1`.
---@param v1 vim.Version|number[]|string Version object.
---@param v2 vim.Version|number[]|string Version to compare with `v1`.
---@return integer -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
function M.cmp(v1, v2)
local v1_parsed = assert(M._version(v1), create_err_msg(v1))
@ -385,40 +388,40 @@ function M.cmp(v1, v2)
end
---Returns `true` if the given versions are equal. See |vim.version.cmp()| for usage.
---@param v1 Version|number[]|string
---@param v2 Version|number[]|string
---@param v1 vim.Version|number[]|string
---@param v2 vim.Version|number[]|string
---@return boolean
function M.eq(v1, v2)
return M.cmp(v1, v2) == 0
end
---Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage.
---@param v1 Version|number[]|string
---@param v2 Version|number[]|string
---@param v1 vim.Version|number[]|string
---@param v2 vim.Version|number[]|string
---@return boolean
function M.le(v1, v2)
return M.cmp(v1, v2) <= 0
end
---Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage.
---@param v1 Version|number[]|string
---@param v2 Version|number[]|string
---@param v1 vim.Version|number[]|string
---@param v2 vim.Version|number[]|string
---@return boolean
function M.lt(v1, v2)
return M.cmp(v1, v2) == -1
end
---Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage.
---@param v1 Version|number[]|string
---@param v2 Version|number[]|string
---@param v1 vim.Version|number[]|string
---@param v2 vim.Version|number[]|string
---@return boolean
function M.ge(v1, v2)
return M.cmp(v1, v2) >= 0
end
---Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage.
---@param v1 Version|number[]|string
---@param v2 Version|number[]|string
---@param v1 vim.Version|number[]|string
---@param v2 vim.Version|number[]|string
---@return boolean
function M.gt(v1, v2)
return M.cmp(v1, v2) == 1
@ -438,7 +441,7 @@ end
--- - strict (boolean): Default false. If `true`, no coercion is attempted on
--- input not conforming to semver v2.0.0. If `false`, `parse()` attempts to
--- coerce input such as "1.0", "0-x", "tmux 3.2a" into valid versions.
---@return Version? parsed_version Version object or `nil` if input is invalid.
---@return vim.Version? parsed_version Version object or `nil` if input is invalid.
function M.parse(version, opts)
assert(type(version) == 'string', create_err_msg(version))
opts = opts or { strict = false }
@ -447,9 +450,9 @@ end
setmetatable(M, {
--- Returns the current Nvim version.
---@return Version
---@return vim.Version
__call = function()
local version = vim.fn.api_info().version ---@type Version
local version = vim.fn.api_info().version ---@type vim.Version
-- Workaround: vim.fn.api_info().version reports "prerelease" as a boolean.
version.prerelease = version.prerelease and 'dev' or nil
return setmetatable(version, Version)

View File

@ -752,7 +752,7 @@ end
---
--- @param fname string help file to parse
--- @param parser_path string? path to non-default vimdoc.so
--- @return LanguageTree, integer (lang_tree, bufnr)
--- @return vim.treesitter.LanguageTree, integer (lang_tree, bufnr)
local function parse_buf(fname, parser_path)
local buf ---@type integer
if type(fname) == 'string' then

View File

@ -269,6 +269,7 @@ local config = {
filename = 'lsp.txt',
section_order = {
'lsp.lua',
'client.lua',
'buf.lua',
'diagnostic.lua',
'codelens.lua',
@ -362,15 +363,25 @@ local function replace_generics(ty, generics)
return generics[ty] or ty
end
--- @param name string
local function fmt_field_name(name)
local name0, opt = name:match('^([^?]*)(%??)$')
return fmt('{%s}%s', name0, opt)
end
--- @param ty string
--- @param generics? table<string,string>
local function render_type(ty, generics)
--- @param default? string
local function render_type(ty, generics, default)
if generics then
ty = replace_generics(ty, generics)
end
ty = ty:gsub('%s*|%s*nil', '?')
ty = ty:gsub('nil%s*|%s*(.*)', '%1?')
ty = ty:gsub('%s*|%s*', '|')
if default then
return fmt('(`%s`, default: %s)', ty, default)
end
return fmt('(`%s`)', ty)
end
@ -379,10 +390,101 @@ local function should_render_param(p)
return not p.access and not contains(p.name, { '_', 'self' })
end
--- @param desc? string
--- @return string?, string?
local function get_default(desc)
if not desc then
return
end
local default = desc:match('\n%s*%([dD]efault: ([^)]+)%)')
if default then
desc = desc:gsub('\n%s*%([dD]efault: [^)]+%)', '')
end
return desc, default
end
--- @param ty string
--- @param classes? table<string,nvim.luacats.parser.class>
--- @return nvim.luacats.parser.class?
local function get_class(ty, classes)
if not classes then
return
end
local cty = ty:gsub('%s*|%s*nil', '?'):gsub('?$', ''):gsub('%[%]$', '')
return classes[cty]
end
--- @param obj nvim.luacats.parser.param|nvim.luacats.parser.return|nvim.luacats.parser.field
--- @param classes? table<string,nvim.luacats.parser.class>
local function inline_type(obj, classes)
local ty = obj.type
if not ty then
return
end
local cls = get_class(ty, classes)
if not cls or cls.nodoc then
return
end
if not cls.inlinedoc then
-- Not inlining so just add a: "See |tag|."
local tag = fmt('|%s|', cls.name)
if obj.desc and obj.desc:find(tag) then
-- Tag already there
return
end
-- TODO(lewis6991): Aim to remove this. Need this to prevent dead
-- references to types defined in runtime/lua/vim/lsp/_meta/protocol.lua
if not vim.startswith(cls.name, 'vim.') then
return
end
obj.desc = obj.desc or ''
local period = (obj.desc == '' or vim.endswith(obj.desc, '.')) and '' or '.'
obj.desc = obj.desc .. fmt('%s See %s.', period, tag)
return
end
local ty_isopt = (ty:match('%?$') or ty:match('%s*|%s*nil')) ~= nil
local ty_islist = (ty:match('%[%]$')) ~= nil
ty = ty_isopt and 'table?' or ty_islist and 'table[]' or 'table'
local desc = obj.desc or ''
if cls.desc then
desc = desc .. cls.desc
elseif desc == '' then
if ty_islist then
desc = desc .. 'A list of objects with the following fields:'
else
desc = desc .. 'A table with the following fields:'
end
end
local desc_append = {}
for _, f in ipairs(cls.fields) do
local fdesc, default = get_default(f.desc)
local fty = render_type(f.type, nil, default)
local fnm = fmt_field_name(f.name)
table.insert(desc_append, table.concat({ '-', fnm, fty, fdesc }, ' '))
end
desc = desc .. '\n' .. table.concat(desc_append, '\n')
obj.type = ty
obj.desc = desc
end
--- @param xs (nvim.luacats.parser.param|nvim.luacats.parser.field)[]
--- @param generics? table<string,string>
--- @param classes? table<string,nvim.luacats.parser.class>
--- @param exclude_types? true
local function render_fields_or_params(xs, generics, exclude_types)
local function render_fields_or_params(xs, generics, classes, exclude_types)
local ret = {} --- @type string[]
xs = vim.tbl_filter(should_render_param, xs)
@ -398,15 +500,27 @@ local function render_fields_or_params(xs, generics, exclude_types)
end
for _, p in ipairs(xs) do
local nm, ty = p.name, p.type
local desc = p.desc
local pnm = fmt(' • %-' .. indent .. 's', '{' .. nm .. '}')
local pdesc, default = get_default(p.desc)
p.desc = pdesc
inline_type(p, classes)
local nm, ty, desc = p.name, p.type, p.desc
local fnm = p.kind == 'operator' and fmt('op(%s)', nm) or fmt_field_name(nm)
local pnm = fmt(' • %-' .. indent .. 's', fnm)
if ty then
local pty = render_type(ty, generics)
local pty = render_type(ty, generics, default)
if desc then
desc = fmt('%s %s', pty, desc)
table.insert(ret, pnm)
table.insert(ret, md_to_vimdoc(desc, 1, 9 + indent, TEXT_WIDTH, true))
if #pty > TEXT_WIDTH - indent then
vim.list_extend(ret, { ' ', pty, '\n' })
table.insert(ret, md_to_vimdoc(desc, 9 + indent, 9 + indent, TEXT_WIDTH, true))
else
desc = fmt('%s %s', pty, desc)
table.insert(ret, md_to_vimdoc(desc, 1, 9 + indent, TEXT_WIDTH, true))
end
else
table.insert(ret, fmt('%s %s\n', pnm, pty))
end
@ -421,24 +535,46 @@ local function render_fields_or_params(xs, generics, exclude_types)
return table.concat(ret)
end
-- --- @param class lua2vimdoc.class
-- local function render_class(class)
-- writeln(fmt('*%s*', class.name))
-- writeln()
-- if #class.fields > 0 then
-- writeln(' Fields: ~')
-- render_fields_or_params(class.fields)
-- end
-- writeln()
-- end
--- @param class nvim.luacats.parser.class
local function render_class(class)
if class.access or class.nodoc or class.inlinedoc then
return
end
-- --- @param cls table<string,lua2vimdoc.class>
-- local function render_classes(cls)
-- --- @diagnostic disable-next-line:no-unknown
-- for _, class in vim.spairs(cls) do
-- render_class(class)
-- end
-- end
local ret = {} --- @type string[]
table.insert(ret, fmt('*%s*\n', class.name))
if class.parent then
local txt = fmt('Extends: |%s|', class.parent)
table.insert(ret, md_to_vimdoc(txt, INDENTATION, INDENTATION, TEXT_WIDTH))
end
if class.desc then
table.insert(ret, md_to_vimdoc(class.desc, INDENTATION, INDENTATION, TEXT_WIDTH))
end
local fields_txt = render_fields_or_params(class.fields)
if not fields_txt:match('^%s*$') then
table.insert(ret, '\n Fields: ~\n')
table.insert(ret, fields_txt)
end
table.insert(ret, '\n')
return table.concat(ret)
end
--- @param cls table<string,nvim.luacats.parser.class>
local function render_classes(cls)
local ret = {} --- @type string[]
--- @diagnostic disable-next-line:no-unknown
for _, class in vim.spairs(cls) do
ret[#ret + 1] = render_class(class)
end
return table.concat(ret)
end
--- @param fun nvim.luacats.parser.fun
--- @param cfg nvim.gen_vimdoc.Config
@ -448,7 +584,7 @@ local function render_fun_header(fun, cfg)
local args = {} --- @type string[]
for _, p in ipairs(fun.params or {}) do
if p.name ~= 'self' then
args[#args + 1] = fmt('{%s}', p.name:gsub('%?$', ''))
args[#args + 1] = fmt_field_name(p.name)
end
end
@ -480,8 +616,9 @@ end
--- @param returns nvim.luacats.parser.return[]
--- @param generics? table<string,string>
--- @param classes? table<string,nvim.luacats.parser.class>
--- @param exclude_types boolean
local function render_returns(returns, generics, exclude_types)
local function render_returns(returns, generics, classes, exclude_types)
local ret = {} --- @type string[]
returns = vim.deepcopy(returns)
@ -498,26 +635,26 @@ local function render_returns(returns, generics, exclude_types)
end
for _, p in ipairs(returns) do
inline_type(p, classes)
local rnm, ty, desc = p.name, p.type, p.desc
local blk = ''
local blk = {} --- @type string[]
if ty then
blk = render_type(ty, generics)
blk[#blk + 1] = render_type(ty, generics)
end
if rnm then
blk = blk .. ' ' .. rnm
end
if desc then
blk = blk .. ' ' .. desc
end
table.insert(ret, md_to_vimdoc(blk, 8, 8, TEXT_WIDTH, true))
blk[#blk + 1] = rnm
blk[#blk + 1] = desc
table.insert(ret, md_to_vimdoc(table.concat(blk, ' '), 8, 8, TEXT_WIDTH, true))
end
return table.concat(ret)
end
--- @param fun nvim.luacats.parser.fun
--- @param classes table<string,nvim.luacats.parser.class>
--- @param cfg nvim.gen_vimdoc.Config
local function render_fun(fun, cfg)
local function render_fun(fun, classes, cfg)
if fun.access or fun.deprecated or fun.nodoc then
return
end
@ -570,7 +707,7 @@ local function render_fun(fun, cfg)
end
if fun.params and #fun.params > 0 then
local param_txt = render_fields_or_params(fun.params, fun.generics, cfg.exclude_types)
local param_txt = render_fields_or_params(fun.params, fun.generics, classes, cfg.exclude_types)
if not param_txt:match('^%s*$') then
table.insert(ret, '\n Parameters: ~\n')
ret[#ret + 1] = param_txt
@ -578,7 +715,7 @@ local function render_fun(fun, cfg)
end
if fun.returns then
local txt = render_returns(fun.returns, fun.generics, cfg.exclude_types)
local txt = render_returns(fun.returns, fun.generics, classes, cfg.exclude_types)
if not txt:match('^%s*$') then
table.insert(ret, '\n')
ret[#ret + 1] = txt
@ -597,15 +734,16 @@ local function render_fun(fun, cfg)
end
--- @param funs nvim.luacats.parser.fun[]
--- @param classes table<string,nvim.luacats.parser.class>
--- @param cfg nvim.gen_vimdoc.Config
local function render_funs(funs, cfg)
local function render_funs(funs, classes, cfg)
local ret = {} --- @type string[]
for _, f in ipairs(funs) do
if cfg.fn_xform then
cfg.fn_xform(f)
end
ret[#ret + 1] = render_fun(f, cfg)
ret[#ret + 1] = render_fun(f, classes, cfg)
end
-- Sort via prototype
@ -745,15 +883,35 @@ local function gen_target(cfg)
expand_files(cfg.files)
--- @type table<string,{[1]:table<string,nvim.luacats.parser.class>, [2]: nvim.luacats.parser.fun[], [3]: string[]}>
local file_results = {}
--- @type table<string,nvim.luacats.parser.class>
local all_classes = {}
--- First pass so we can collect all classes
for _, f in pairs(cfg.files) do
local ext = assert(f:match('%.([^.]+)$')) --[[@as 'h'|'c'|'lua']]
local parser = assert(parsers[ext])
local _, funs, briefs = parser(f)
local classes, funs, briefs = parser(f)
file_results[f] = { classes, funs, briefs }
all_classes = vim.tbl_extend('error', all_classes, classes)
end
for f, r in pairs(file_results) do
local classes, funs, briefs = r[1], r[2], r[3]
local briefs_txt = {} --- @type string[]
for _, b in ipairs(briefs) do
briefs_txt[#briefs_txt + 1] = md_to_vimdoc(b, 0, 0, TEXT_WIDTH)
end
local funs_txt = render_funs(funs, cfg)
local funs_txt = render_funs(funs, all_classes, cfg)
if next(classes) then
local classes_txt = render_classes(classes)
if vim.trim(classes_txt) ~= '' then
funs_txt = classes_txt .. '\n' .. funs_txt
end
end
-- FIXME: Using f_base will confuse `_meta/protocol.lua` with `protocol.lua`
local f_base = assert(vim.fs.basename(f))
sections[f_base] = make_section(f_base, cfg, briefs_txt, funs_txt)

View File

@ -21,8 +21,7 @@ local function opt(x)
return x ^ -1
end
local nl = P('\r\n') + P('\n')
local ws = rep1(S(' \t') + nl)
local ws = rep1(S(' \t'))
local fill = opt(ws)
local any = P(1) -- (consume one character)
@ -30,11 +29,11 @@ local letter = R('az', 'AZ') + S('_$')
local num = R('09')
local ident = letter * rep(letter + num + S '-.')
local string_single = P "'" * rep(any - P "'") * P "'"
local string_double = P '"' * rep(any - P '"') * P '"'
local string_double = P('"') * rep(any - P('"')) * P('"')
local literal = (string_single + string_double + (opt(P '-') * num) + P 'false' + P 'true')
local literal = (string_single + string_double + (opt(P('-')) * num) + P('false') + P('true'))
local lname = (ident + P '...') * opt(P '?')
local lname = (ident + P('...')) * opt(P('?'))
--- @param x string
local function Pf(x)
@ -47,13 +46,23 @@ local function Sf(x)
end
--- @param x vim.lpeg.Pattern
local function comma(x)
return x * rep(Pf ',' * x)
local function paren(x)
return Pf('(') * x * fill * P(')')
end
--- @param x vim.lpeg.Pattern
local function parenOpt(x)
return (Pf('(') * x * fill * P(')')) + x
return paren(x) + x
end
--- @param x vim.lpeg.Pattern
local function comma1(x)
return parenOpt(x * rep(Pf(',') * x))
end
--- @param x vim.lpeg.Pattern
local function comma(x)
return opt(comma1(x))
end
--- @type table<string,vim.lpeg.Pattern>
@ -63,7 +72,15 @@ local v = setmetatable({}, {
end,
})
local colon = Pf(':')
local opt_exact = opt(Cg(Pf('(exact)'), 'access'))
local access = P('private') + P('protected') + P('package')
local caccess = Cg(access, 'access')
local desc_delim = Sf '#:' + ws
local desc = Cg(rep(any), 'desc')
local opt_desc = opt(desc_delim * desc)
local cname = Cg(ident, 'name')
local opt_parent = opt(colon * Cg(ident, 'parent'))
--- @class nvim.luacats.Param
--- @field kind 'param'
@ -85,6 +102,7 @@ local desc_delim = Sf '#:' + ws
--- @field kind 'class'
--- @field name string
--- @field parent? string
--- @field access? 'private'|'protected'|'package'
--- @class nvim.luacats.Field
--- @field kind 'field'
@ -107,112 +125,60 @@ local desc_delim = Sf '#:' + ws
--- @class nvim.luacats.grammar
--- @field match fun(self, input: string): nvim.luacats.grammar.result?
local function annot(nm, pat)
if type(nm) == 'string' then
nm = P(nm)
end
if pat then
return Ct(Cg(P(nm), 'kind') * fill * pat)
end
return Ct(Cg(P(nm), 'kind'))
end
local grammar = P {
rep1(P('@') * (v.ats + v.ext_ats)),
ats = v.at_param
+ v.at_return
+ v.at_type
+ v.at_cast
+ v.at_generic
+ v.at_class
+ v.at_field
+ v.at_access
+ v.at_deprecated
+ v.at_alias
+ v.at_enum
+ v.at_see
+ v.at_diagnostic
+ v.at_overload
+ v.at_meta,
ext_ats = v.ext_at_note + v.ext_at_since + v.ext_at_nodoc + v.ext_at_brief,
at_param = Ct(
Cg(P('param'), 'kind')
* ws
* Cg(lname, 'name')
* ws
* parenOpt(Cg(v.ltype, 'type'))
* opt(desc_delim * Cg(rep(any), 'desc'))
),
at_return = Ct(
Cg(P('return'), 'kind')
* ws
* parenOpt(comma(Ct(Cg(v.ltype, 'type') * opt(ws * Cg(ident, 'name')))))
* opt(desc_delim * Cg(rep(any), 'desc'))
),
at_type = Ct(
Cg(P('type'), 'kind')
* ws
* parenOpt(comma(Ct(Cg(v.ltype, 'type'))))
* opt(desc_delim * Cg(rep(any), 'desc'))
),
at_cast = Ct(
Cg(P('cast'), 'kind') * ws * Cg(lname, 'name') * ws * opt(Sf('+-')) * Cg(v.ltype, 'type')
),
at_generic = Ct(
Cg(P('generic'), 'kind') * ws * Cg(ident, 'name') * opt(Pf ':' * Cg(v.ltype, 'type'))
),
at_class = Ct(
Cg(P('class'), 'kind')
* ws
* opt(P('(exact)') * ws)
* Cg(lname, 'name')
* opt(Pf(':') * Cg(lname, 'parent'))
),
at_field = Ct(
Cg(P('field'), 'kind')
* ws
* opt(Cg(Pf('private') + Pf('package') + Pf('protected'), 'access'))
* Cg(lname, 'name')
* ws
* Cg(v.ltype, 'type')
* opt(desc_delim * Cg(rep(any), 'desc'))
),
at_access = Ct(Cg(P('private') + P('protected') + P('package'), 'kind')),
at_deprecated = Ct(Cg(P('deprecated'), 'kind')),
-- Types may be provided on subsequent lines
at_alias = Ct(Cg(P('alias'), 'kind') * ws * Cg(lname, 'name') * opt(ws * Cg(v.ltype, 'type'))),
at_enum = Ct(Cg(P('enum'), 'kind') * ws * Cg(lname, 'name')),
at_see = Ct(Cg(P('see'), 'kind') * ws * opt(Pf('#')) * Cg(rep(any), 'desc')),
at_diagnostic = Ct(Cg(P('diagnostic'), 'kind') * ws * opt(Pf('#')) * Cg(rep(any), 'desc')),
at_overload = Ct(Cg(P('overload'), 'kind') * ws * Cg(v.ltype, 'type')),
at_meta = Ct(Cg(P('meta'), 'kind')),
ats = annot('param', Cg(lname, 'name') * ws * v.ctype * opt_desc)
+ annot('return', comma1(Ct(v.ctype * opt(ws * cname))) * opt_desc)
+ annot('type', comma1(Ct(v.ctype)) * opt_desc)
+ annot('cast', cname * ws * opt(Sf('+-')) * v.ctype)
+ annot('generic', cname * opt(colon * v.ctype))
+ annot('class', opt_exact * opt(paren(caccess)) * fill * cname * opt_parent)
+ annot('field', opt(caccess * ws) * v.field_name * ws * v.ctype * opt_desc)
+ annot('operator', cname * opt(paren(Cg(v.ltype, 'argtype'))) * colon * v.ctype)
+ annot(access)
+ annot('deprecated')
+ annot('alias', cname * opt(ws * v.ctype))
+ annot('enum', cname)
+ annot('overload', v.ctype)
+ annot('see', opt(desc_delim) * desc)
+ annot('diagnostic', opt(desc_delim) * desc)
+ annot('meta'),
--- Custom extensions
ext_at_note = Ct(Cg(P('note'), 'kind') * ws * Cg(rep(any), 'desc')),
ext_ats = (
annot('note', desc)
+ annot('since', desc)
+ annot('nodoc')
+ annot('inlinedoc')
+ annot('brief', desc)
),
-- TODO only consume 1 line
ext_at_since = Ct(Cg(P('since'), 'kind') * ws * Cg(rep(any), 'desc')),
field_name = Cg(lname + (v.ty_index * opt(P('?'))), 'name'),
ext_at_nodoc = Ct(Cg(P('nodoc'), 'kind')),
ext_at_brief = Ct(Cg(P('brief'), 'kind') * opt(ws * Cg(rep(any), 'desc'))),
ctype = parenOpt(Cg(v.ltype, 'type')),
ltype = parenOpt(v.ty_union),
ltype = v.ty_union + Pf '(' * v.ty_union * fill * P ')',
ty_union = v.ty_opt * rep(Pf '|' * v.ty_opt),
ty_union = v.ty_opt * rep(Pf('|') * v.ty_opt),
ty = v.ty_fun + ident + v.ty_table + literal,
ty_param = Pf '<' * comma(v.ltype) * fill * P '>',
ty_opt = v.ty * opt(v.ty_param) * opt(P '[]') * opt(P '?'),
table_key = (Pf '[' * literal * Pf ']') + lname,
table_elem = v.table_key * Pf ':' * v.ltype,
ty_table = Pf '{' * comma(v.table_elem) * Pf '}',
fun_param = lname * opt(Pf ':' * v.ltype),
ty_fun = Pf 'fun(' * rep(comma(v.fun_param)) * fill * P ')' * opt(Pf ':' * comma(v.ltype)),
ty_param = Pf('<') * comma1(v.ltype) * fill * P('>'),
ty_opt = v.ty * opt(v.ty_param) * opt(P('[]')) * opt(P('?')),
ty_index = (Pf('[') * v.ltype * Pf(']')),
table_key = v.ty_index + lname,
table_elem = v.table_key * colon * v.ltype,
ty_table = Pf('{') * comma1(v.table_elem) * Pf('}'),
fun_param = lname * opt(colon * v.ltype),
ty_fun = Pf('fun') * paren(comma(lname * opt(colon * v.ltype))) * opt(colon * comma1(v.ltype)),
}
return grammar --[[@as nvim.luacats.grammar]]

View File

@ -19,7 +19,7 @@ local luacats_grammar = require('scripts.luacats_grammar')
--- @class nvim.luacats.parser.alias
--- @field kind 'alias'
--- @field type string
--- @field type string[]
--- @field desc string
--- @class nvim.luacats.parser.fun
@ -49,8 +49,12 @@ local luacats_grammar = require('scripts.luacats_grammar')
--- @class nvim.luacats.parser.class
--- @field kind 'class'
--- @field parent? string
--- @field name string
--- @field desc string
--- @field nodoc? true
--- @field inlinedoc? true
--- @field access? 'private'|'package'|'protected'
--- @field fields nvim.luacats.parser.field[]
--- @field notes? string[]
@ -64,6 +68,7 @@ local luacats_grammar = require('scripts.luacats_grammar')
--- | nvim.luacats.parser.class
--- | nvim.luacats.parser.fun
--- | nvim.luacats.parser.brief
--- | nvim.luacats.parser.alias
-- Remove this when we document classes properly
--- Some doc lines have the form:
@ -142,22 +147,27 @@ local function process_doc_line(line, state)
}
elseif kind == 'class' then
--- @cast parsed nvim.luacats.Class
state.cur_obj = {
kind = 'class',
name = parsed.name,
parent = parsed.parent,
desc = '',
fields = {},
}
cur_obj.kind = 'class'
cur_obj.name = parsed.name
cur_obj.parent = parsed.parent
cur_obj.access = parsed.access
cur_obj.desc = state.doc_lines and table.concat(state.doc_lines, '\n') or nil
state.doc_lines = nil
cur_obj.fields = {}
elseif kind == 'field' then
--- @cast parsed nvim.luacats.Field
if not parsed.access then
parsed.desc = parsed.desc or state.doc_lines and table.concat(state.doc_lines, '\n') or nil
if parsed.desc then
parsed.desc = vim.trim(parsed.desc)
end
table.insert(cur_obj.fields, parsed)
parsed.desc = parsed.desc or state.doc_lines and table.concat(state.doc_lines, '\n') or nil
if parsed.desc then
parsed.desc = vim.trim(parsed.desc)
end
table.insert(cur_obj.fields, parsed)
state.doc_lines = nil
elseif kind == 'operator' then
parsed.desc = parsed.desc or state.doc_lines and table.concat(state.doc_lines, '\n') or nil
if parsed.desc then
parsed.desc = vim.trim(parsed.desc)
end
table.insert(cur_obj.fields, parsed)
state.doc_lines = nil
elseif kind == 'param' then
state.last_doc_item_indent = nil
@ -191,6 +201,8 @@ local function process_doc_line(line, state)
cur_obj.access = 'protected'
elseif kind == 'deprecated' then
cur_obj.deprecated = true
elseif kind == 'inlinedoc' then
cur_obj.inlinedoc = true
elseif kind == 'nodoc' then
cur_obj.nodoc = true
elseif kind == 'since' then
@ -383,11 +395,11 @@ end
--- Determine the table name used to export functions of a module
--- Usually this is `M`.
--- @param filename string
--- @param str string
--- @return string?
local function determine_modvar(filename)
local function determine_modvar(str)
local modvar --- @type string?
for line in io.lines(filename) do
for line in vim.gsplit(str, '\n') do
do
--- @type string?
local m = line:match('^return%s+([a-zA-Z_]+)')
@ -462,17 +474,12 @@ end
local M = {}
--- @param filename string
--- @return table<string,nvim.luacats.parser.class> classes
--- @return nvim.luacats.parser.fun[] funs
--- @return string[] briefs
--- @return nvim.luacats.parser.obj[]
function M.parse(filename)
function M.parse_str(str, filename)
local funs = {} --- @type nvim.luacats.parser.fun[]
local classes = {} --- @type table<string,nvim.luacats.parser.class>
local briefs = {} --- @type string[]
local mod_return = determine_modvar(filename)
local mod_return = determine_modvar(str)
--- @type string
local module = filename:match('.*/lua/([a-z_][a-z0-9_/]+)%.lua') or filename
@ -485,7 +492,7 @@ function M.parse(filename)
-- Keep track of any partial objects we don't commit
local uncommitted = {} --- @type nvim.luacats.parser.obj[]
for line in io.lines(filename) do
for line in vim.gsplit(str, '\n') do
local has_indent = line:match('^%s+') ~= nil
line = vim.trim(line)
if vim.startswith(line, '---') then
@ -518,4 +525,13 @@ function M.parse(filename)
return classes, funs, briefs, uncommitted
end
--- @param filename string
function M.parse(filename)
local f = assert(io.open(filename, 'r'))
local txt = f:read('*all')
f:close()
return M.parse_str(txt, filename)
end
return M

View File

@ -175,7 +175,11 @@ local function render_md(node, start_indent, indent, text_width, level, is_list)
error(fmt('cannot render:\n%s', vim.inspect(node)))
end
for i, child in ipairs(node) do
vim.list_extend(parts, render_md(child, start_indent, indent, text_width, level + 1, is_list))
local start_indent0 = i == 1 and start_indent or indent
vim.list_extend(
parts,
render_md(child, start_indent0, indent, text_width, level + 1, is_list)
)
if node.type ~= 'list' and i ~= #node then
if (node[i + 1] or {}).type ~= 'list' then
parts[#parts + 1] = '\n'

View File

@ -0,0 +1,106 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local parser = require('scripts/luacats_parser')
--- @param name string
--- @param text string
--- @param exp table<string,string>
local function test(name, text, exp)
exp = vim.deepcopy(exp, true)
it(name, function()
eq(exp, parser.parse_str(text, 'myfile.lua'))
end)
end
describe('luacats parser', function()
local exp = {
myclass = {
kind = 'class',
module = 'myfile.lua',
name = 'myclass',
fields = {
{ kind = 'field', name = 'myclass', type = 'integer' },
},
},
}
test(
'basic class',
[[
--- @class myclass
--- @field myclass integer
]],
exp
)
exp.myclass.inlinedoc = true
test(
'class with @inlinedoc (1)',
[[
--- @class myclass
--- @inlinedoc
--- @field myclass integer
]],
exp
)
test(
'class with @inlinedoc (2)',
[[
--- @inlinedoc
--- @class myclass
--- @field myclass integer
]],
exp
)
exp.myclass.inlinedoc = nil
exp.myclass.nodoc = true
test(
'class with @nodoc',
[[
--- @nodoc
--- @class myclass
--- @field myclass integer
]],
exp
)
exp.myclass.nodoc = nil
exp.myclass.access = 'private'
test(
'class with (private)',
[[
--- @class (private) myclass
--- @field myclass integer
]],
exp
)
exp.myclass.fields[1].desc = 'Field\ndocumentation'
test(
'class with field doc above',
[[
--- @class (private) myclass
--- Field
--- documentation
--- @field myclass integer
]],
exp
)
exp.myclass.fields[1].desc = 'Field documentation'
test(
'class with field doc inline',
[[
--- @class (private) myclass
--- @field myclass integer Field documentation
]],
exp
)
end)

View File

@ -2,18 +2,28 @@ local helpers = require('test.functional.helpers')(after_each)
local exec_lua = helpers.exec_lua
local eq = helpers.eq
local function md_to_vimdoc(text)
local function md_to_vimdoc(text, start_indent, indent, text_width)
return exec_lua(
[[
local text, start_indent, indent, text_width = ...
start_indent = start_indent or 0
indent = indent or 0
text_width = text_width or 70
local text_utils = require('scripts/text_utils')
return text_utils.md_to_vimdoc(table.concat(..., '\n'), 0, 0, 70)
return text_utils.md_to_vimdoc(table.concat(text, '\n'), start_indent, indent, text_width)
]],
text
text,
start_indent,
indent,
text_width
)
end
local function test(act, exp)
eq(table.concat(exp, '\n'), md_to_vimdoc(act))
local function test(what, act, exp, ...)
local argc, args = select('#', ...), { ... }
it(what, function()
eq(table.concat(exp, '\n'), md_to_vimdoc(act, unpack(args, 1, argc)))
end)
end
describe('md_to_vimdoc', function()
@ -21,19 +31,28 @@ describe('md_to_vimdoc', function()
helpers.clear()
end)
it('can render para after fenced code', function()
test({
'- Para1',
' ```',
' code',
' ```',
' Para2',
}, {
'• Para1 >',
' code',
'<',
' Para2',
'',
})
end)
test('can render para after fenced code', {
'- Para1',
' ```',
' code',
' ```',
' Para2',
}, {
'• Para1 >',
' code',
'<',
' Para2',
'',
})
test('start_indent only applies to first line', {
'para1',
'',
'para2',
}, {
'para1',
'',
' para2',
'',
}, 0, 10, 78)
end)