diff options
author | Lewis Russell <lewis6991@gmail.com> | 2024-10-29 09:36:02 +0000 |
---|---|---|
committer | Lewis Russell <me@lewisr.dev> | 2024-11-01 09:17:39 +0000 |
commit | 9b357e30fdd0a575480182872331fdb87e9cc331 (patch) | |
tree | 02e7a8ce3fcd70946acca8e27d2769dfcf75b6e3 | |
parent | f54266dbed6f1a4cb4fad3486a722a25070d7feb (diff) | |
download | rneovim-9b357e30fdd0a575480182872331fdb87e9cc331.tar.gz rneovim-9b357e30fdd0a575480182872331fdb87e9cc331.tar.bz2 rneovim-9b357e30fdd0a575480182872331fdb87e9cc331.zip |
feat(lsp)!: remove client-server handlers from vim.lsp.handlers
- Partition the handlers in vim.lsp.handlers as:
- client to server response handlers (RCS)
- server to client request handlers (RSC)
- server to client notification handlers (NSC)
Note use string indexes instead of protocol.methods for improved
typing in LuaLS (tip: use hover on RCS, RSC or NSC).
-rw-r--r-- | runtime/doc/deprecated.txt | 6 | ||||
-rw-r--r-- | runtime/doc/lsp.txt | 277 | ||||
-rw-r--r-- | runtime/doc/news-0.10.txt | 2 | ||||
-rw-r--r-- | runtime/doc/news.txt | 8 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_meta.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 66 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/codelens.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/diagnostic.lua | 83 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 173 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/inlay_hint.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 104 | ||||
-rw-r--r-- | scripts/gen_lsp.lua | 43 | ||||
-rw-r--r-- | test/functional/plugin/lsp/diagnostic_spec.lua | 107 |
14 files changed, 409 insertions, 471 deletions
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 9c973b20bd..5e809ad26c 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -50,6 +50,12 @@ LSP • *vim.lsp.buf.completion* Use |vim.lsp.completion.trigger()| instead. • vim.lsp.buf_request_all The `error` key has been renamed to `err` inside the result parameter of the handler. +• *vim.lsp.with()* Pass configuration to equivalent + functions in `vim.lsp.buf.*'. +• |vim.lsp.handlers| + No longer support client to server response handlers. Only server to + client requests/notification handlers are supported. +• *vim.lsp.handlers.signature_help()* Use |vim.lsp.buf.signature_help()| instead. ------------------------------------------------------------------------------ DEPRECATED IN 0.10 *deprecated-0.10* diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 804eb171f7..6e5c85c019 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -195,41 +195,41 @@ Requests and notifications defined by the LSP specification are referred to as They are also listed below. Note that handlers depend on server support: they won't run if your server doesn't support them. -- callHierarchy/incomingCalls -- callHierarchy/outgoingCalls -- textDocument/codeAction -- textDocument/completion -- textDocument/declaration* -- textDocument/definition -- textDocument/diagnostic -- textDocument/documentHighlight -- textDocument/documentSymbol -- textDocument/formatting -- textDocument/hover -- textDocument/implementation* -- textDocument/inlayHint -- textDocument/prepareTypeHierarchy -- textDocument/publishDiagnostics -- textDocument/rangeFormatting -- textDocument/rangesFormatting -- textDocument/references -- textDocument/rename -- textDocument/semanticTokens/full -- textDocument/semanticTokens/full/delta -- textDocument/signatureHelp -- textDocument/typeDefinition* -- typeHierarchy/subtypes -- typeHierarchy/supertypes -- window/logMessage -- window/showMessage -- window/showDocument -- window/showMessageRequest -- workspace/applyEdit -- workspace/configuration -- workspace/executeCommand -- workspace/inlayHint/refresh -- workspace/symbol -- workspace/workspaceFolders +- `'callHierarchy/incomingCalls'` +- `'callHierarchy/outgoingCalls'` +- `'textDocument/codeAction'` +- `'textDocument/completion'` +- `'textDocument/declaration'` +- `'textDocument/definition'` +- `'textDocument/diagnostic'` +- `'textDocument/documentHighlight'` +- `'textDocument/documentSymbol'` +- `'textDocument/formatting'` +- `'textDocument/hover'` +- `'textDocument/implementation'` +- `'textDocument/inlayHint'` +- `'textDocument/prepareTypeHierarchy'` +- `'textDocument/publishDiagnostics'` +- `'textDocument/rangeFormatting'` +- `'textDocument/rangesFormatting'` +- `'textDocument/references'` +- `'textDocument/rename'` +- `'textDocument/semanticTokens/full'` +- `'textDocument/semanticTokens/full/delta'` +- `'textDocument/signatureHelp'` +- `'textDocument/typeDefinition*'` +- `'typeHierarchy/subtypes'` +- `'typeHierarchy/supertypes'` +- `'window/logMessage'` +- `'window/showMessage'` +- `'window/showDocument'` +- `'window/showMessageRequest'` +- `'workspace/applyEdit'` +- `'workspace/configuration'` +- `'workspace/executeCommand'` +- `'workspace/inlayHint/refresh'` +- `'workspace/symbol'` +- `'workspace/workspaceFolders'` *lsp-handler* LSP handlers are functions that handle |lsp-response|s to requests made by Nvim @@ -238,7 +238,7 @@ there is no response, so they can't be handled. |lsp-notification|) Each response handler has this signature: > - function(err, result, ctx, config) + function(err, result, ctx) < Parameters: ~ • {err} (`table|nil`) Error info dict, or `nil` if the request @@ -255,121 +255,53 @@ Each response handler has this signature: > request. Handlers can compare this to the current document version to check if the response is "stale". See also |b:changedtick|. - • {config} (`table`) Handler-defined configuration table, which allows - users to customize handler behavior. - For an example, see: - |vim.lsp.diagnostic.on_publish_diagnostics()| - To configure a particular |lsp-handler|, see: - |lsp-handler-configuration| Returns: ~ Two values `result, err` where `err` is shaped like an RPC error: > { code, message, data? } < You can use |vim.lsp.rpc.rpc_response_error()| to create this object. - *lsp-handler-configuration* - -To configure the behavior of a builtin |lsp-handler|, the convenient method -|vim.lsp.with()| is provided for users. - - To configure the behavior of |vim.lsp.diagnostic.on_publish_diagnostics()|, - consider the following example, where a new |lsp-handler| is created using - |vim.lsp.with()| that no longer generates signs for the diagnostics: >lua - - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Disable signs - signs = false, - } - ) -< - To enable signs, use |vim.lsp.with()| again to create and assign a new - |lsp-handler| to |vim.lsp.handlers| for the associated method: >lua - - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Enable signs - signs = true, - } - ) -< - To configure a handler on a per-server basis, you can use the {handlers} key - for |vim.lsp.start_client()| >lua - - vim.lsp.start_client { - ..., -- Other configuration omitted. - handlers = { - ["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Disable virtual_text - virtual_text = false, - } - ), - }, - } -< - or if using "nvim-lspconfig", you can use the {handlers} key of `setup()`: - >lua - - require('lspconfig').rust_analyzer.setup { - handlers = { - ["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Disable virtual_text - virtual_text = false - } - ), - } - } -< - Some handlers do not have an explicitly named handler function (such as - |vim.lsp.diagnostic.on_publish_diagnostics()|). To override these, first - create a reference to the existing handler: >lua - - local on_references = vim.lsp.handlers["textDocument/references"] - vim.lsp.handlers["textDocument/references"] = vim.lsp.with( - on_references, { - -- Use location list instead of quickfix list - loclist = true, - } - ) -< *lsp-handler-resolution* -Handlers can be set by: +Handlers can be set by (in increasing priority): - Setting a field in vim.lsp.handlers. *vim.lsp.handlers* - vim.lsp.handlers is a global table that contains the default mapping of - |lsp-method| names to |lsp-handlers|. To override the handler for the - `"textDocument/definition"` method: >lua + `vim.lsp.handlers` is a global table that contains the default mapping of + |lsp-method| names to lsp-handlers. + + Example: >lua - vim.lsp.handlers["textDocument/definition"] = my_custom_default_definition + vim.lsp.handlers['textDocument/publishDiagnostics'] = my_custom_diagnostics_handler < + Note: this only applies for requests/notifications made by the + server to the client. + - The {handlers} parameter of |vim.lsp.start()|. This sets the default - |lsp-handler| for the server being started. Example: >lua + |lsp-handler| for a specific server. + + Example: >lua vim.lsp.start { ..., -- Other configuration omitted. handlers = { - ["textDocument/definition"] = my_custom_server_definition + ['textDocument/publishDiagnostics'] = my_custom_server_definition }, } +< + Note: this only applies for requests/notifications made by the + server to the client. - The {handler} parameter of |vim.lsp.buf_request_all()|. This sets - the |lsp-handler| ONLY for the given request(s). Example: >lua + the |lsp-handler| ONLY for the given request(s). + + Example: >lua vim.lsp.buf_request_all( 0, - "textDocument/definition", + 'textDocument/publishDiagnostics', my_request_params, my_handler ) < -In summary, the |lsp-handler| will be chosen based on the current |lsp-method| -in the following order: - -1. Handler passed to |vim.lsp.buf_request_all()|, if any. -2. Handler defined in |vim.lsp.start()|, if any. -3. Handler defined in |vim.lsp.handlers|, if any. *vim.lsp.log_levels* Log levels are defined in |vim.log.levels| @@ -955,14 +887,6 @@ tagfunc({pattern}, {flags}) *vim.lsp.tagfunc()* Return: ~ (`table[]`) tags A list of matching tags -with({handler}, {override_config}) *vim.lsp.with()* - Function to manage overriding defaults for LSP handlers. - - Parameters: ~ - • {handler} (`lsp.Handler`) See |lsp-handler| - • {override_config} (`table`) Table containing the keys to override - behavior of the {handler} - ============================================================================== Lua module: vim.lsp.client *lsp-client* @@ -1279,6 +1203,13 @@ Lua module: vim.lsp.buf *lsp-buf* Fields: ~ • {silent}? (`boolean`) +*vim.lsp.buf.signature_help.Opts* + Extends: |vim.lsp.util.open_floating_preview.Opts| + + + Fields: ~ + • {silent}? (`boolean`) + *vim.lsp.buf.add_workspace_folder()* add_workspace_folder({workspace_folder}) @@ -1461,10 +1392,14 @@ rename({new_name}, {opts}) *vim.lsp.buf.rename()* ones where client.name matches this field. • {bufnr}? (`integer`) (default: current buffer) -signature_help() *vim.lsp.buf.signature_help()* +signature_help({config}) *vim.lsp.buf.signature_help()* Displays signature information about the symbol under the cursor in a floating window. + Parameters: ~ + • {config} (`vim.lsp.buf.signature_help.Opts?`) See + |vim.lsp.buf.signature_help.Opts|. + type_definition({opts}) *vim.lsp.buf.type_definition()* Jumps to the definition of the type of the symbol under the cursor. @@ -1514,66 +1449,24 @@ get_namespace({client_id}, {is_pull}) client. Defaults to push *vim.lsp.diagnostic.on_diagnostic()* -on_diagnostic({_}, {result}, {ctx}, {config}) +on_diagnostic({_}, {result}, {ctx}) |lsp-handler| for the method "textDocument/diagnostic" - See |vim.diagnostic.config()| for configuration options. Handler-specific - configuration can be set using |vim.lsp.with()|: >lua - vim.lsp.handlers["textDocument/diagnostic"] = vim.lsp.with( - vim.lsp.diagnostic.on_diagnostic, { - -- Enable underline, use default values - underline = true, - -- Enable virtual text, override spacing to 4 - virtual_text = { - spacing = 4, - }, - -- Use a function to dynamically turn signs off - -- and on, using buffer local variables - signs = function(namespace, bufnr) - return vim.b[bufnr].show_signs == true - end, - -- Disable a feature - update_in_insert = false, - } - ) -< + See |vim.diagnostic.config()| for configuration options. Parameters: ~ • {result} (`lsp.DocumentDiagnosticReport`) • {ctx} (`lsp.HandlerContext`) - • {config} (`vim.diagnostic.Opts`) Configuration table (see - |vim.diagnostic.config()|). *vim.lsp.diagnostic.on_publish_diagnostics()* -on_publish_diagnostics({_}, {result}, {ctx}, {config}) +on_publish_diagnostics({_}, {result}, {ctx}) |lsp-handler| for the method "textDocument/publishDiagnostics" - See |vim.diagnostic.config()| for configuration options. Handler-specific - configuration can be set using |vim.lsp.with()|: >lua - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Enable underline, use default values - underline = true, - -- Enable virtual text, override spacing to 4 - virtual_text = { - spacing = 4, - }, - -- Use a function to dynamically turn signs off - -- and on, using buffer local variables - signs = function(namespace, bufnr) - return vim.b[bufnr].show_signs == true - end, - -- Disable a feature - update_in_insert = false, - } - ) -< + See |vim.diagnostic.config()| for configuration options. Parameters: ~ • {result} (`lsp.PublishDiagnosticsParams`) • {ctx} (`lsp.HandlerContext`) - • {config} (`vim.diagnostic.Opts?`) Configuration table (see - |vim.diagnostic.config()|). ============================================================================== @@ -1824,32 +1717,6 @@ stop({bufnr}, {client_id}) *vim.lsp.semantic_tokens.stop()* ============================================================================== -Lua module: vim.lsp.handlers *lsp-handlers* - - *vim.lsp.handlers.signature_help()* -signature_help({_}, {result}, {ctx}, {config}) - |lsp-handler| for the method "textDocument/signatureHelp". - - The active parameter is highlighted with |hl-LspSignatureActiveParameter|. >lua - vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with( - vim.lsp.handlers.signature_help, { - -- Use a sharp border with `FloatBorder` highlights - border = "single" - } - ) -< - - Parameters: ~ - • {result} (`lsp.SignatureHelp?`) Response from the language server - • {ctx} (`lsp.HandlerContext`) Client context - • {config} (`table`) Configuration table. - • border: (default=nil) - • Add borders to the floating window - • See |vim.lsp.util.open_floating_preview()| for more - options - - -============================================================================== Lua module: vim.lsp.util *lsp-util* *vim.lsp.util.open_floating_preview.Opts* diff --git a/runtime/doc/news-0.10.txt b/runtime/doc/news-0.10.txt index a5ded1ca22..35af570ec3 100644 --- a/runtime/doc/news-0.10.txt +++ b/runtime/doc/news-0.10.txt @@ -246,7 +246,7 @@ The following new features were added. indicator to see if a server supports a feature. Instead use `client.supports_method(<method>)`. It considers both the dynamic capabilities and static `server_capabilities`. - • `anchor_bias` option to |lsp-handlers| aids in positioning of floating + • `anchor_bias` option to lsp-handlers aids in positioning of floating windows. • |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to the original LSP `Location` or `LocationLink`. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index c01bb46de7..f82cf4453e 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -87,7 +87,13 @@ LSP but no longer trigger the global handlers from `vim.lsp.handlers` • |vim.lsp.buf.typehierarchy()| now passes the correct params for each client request. - +• |vim.lsp.handlers.signature_help()| is no longer used. +• |vim.lsp.diagnostic.on_publish_diagnostics()| and + |vim.lsp.diagnostic.on_diagnostic()| no longer accept a config parameter and + can no longer be configured with |vim.lsp.with()|. + Instead use: >lua + vim.diagnostic.config(config, vim.lsp.diagnostic.get_namespace(client_id)) +< LUA diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index a8ae283f64..42a0ccc3d4 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1165,6 +1165,7 @@ function lsp.for_each_buffer_client(bufnr, fn) end end +--- @deprecated --- Function to manage overriding defaults for LSP handlers. ---@param handler (lsp.Handler) See |lsp-handler| ---@param override_config (table) Table containing the keys to override behavior of the {handler} diff --git a/runtime/lua/vim/lsp/_meta.lua b/runtime/lua/vim/lsp/_meta.lua index 589a49c003..bf693ccc57 100644 --- a/runtime/lua/vim/lsp/_meta.lua +++ b/runtime/lua/vim/lsp/_meta.lua @@ -1,8 +1,8 @@ ---@meta error('Cannot require a meta file') ----@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext, config?: table): ...any ----@alias lsp.MultiHandler fun(results: table<integer,{err: lsp.ResponseError?, result: any}>, context: lsp.HandlerContext, config?: table): ...any +---@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext): ...any +---@alias lsp.MultiHandler fun(results: table<integer,{err: lsp.ResponseError?, result: any}>, context: lsp.HandlerContext): ...any ---@class lsp.HandlerContext ---@field method string diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 4818359fb3..152226a757 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -258,10 +258,72 @@ function M.implementation(opts) get_locations(ms.textDocument_implementation, opts) end +local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') + +--- @class vim.lsp.buf.signature_help.Opts : vim.lsp.util.open_floating_preview.Opts +--- @field silent? boolean + +-- TODO(lewis6991): support multiple clients --- Displays signature information about the symbol under the cursor in a --- floating window. -function M.signature_help() - lsp.buf_request(0, ms.textDocument_signatureHelp, client_positional_params()) +--- @param config? vim.lsp.buf.signature_help.Opts +function M.signature_help(config) + local method = ms.textDocument_signatureHelp + + config = config or {} + config.focus_id = method + + lsp.buf_request(0, method, client_positional_params(), function(err, result, ctx) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + + if err then + vim.notify( + client.name .. ': ' .. tostring(err.code) .. ': ' .. err.message, + vim.log.levels.ERROR + ) + api.nvim_command('redraw') + return + end + + if api.nvim_get_current_buf() ~= ctx.bufnr then + -- Ignore result since buffer changed. This happens for slow language servers. + return + end + + -- When use `autocmd CompleteDone <silent><buffer> lua vim.lsp.buf.signature_help()` to call signatureHelp handler + -- If the completion item doesn't have signatures It will make noise. Change to use `print` that can use `<silent>` to ignore + if not result or not result.signatures or not result.signatures[1] then + if config.silent ~= true then + print('No signature help available') + end + return + end + + local triggers = + vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters') + + local ft = vim.bo[ctx.bufnr].filetype + local lines, hl = util.convert_signature_help_to_markdown_lines(result, ft, triggers) + if not lines or vim.tbl_isempty(lines) then + if config.silent ~= true then + print('No signature help available') + end + return + end + + local fbuf = util.open_floating_preview(lines, 'markdown', config) + + -- Highlight the active parameter. + if hl then + vim.hl.range( + fbuf, + sig_help_ns, + 'LspSignatureActiveParameter', + { hl[1], hl[2] }, + { hl[3], hl[4] } + ) + end + end) end --- @deprecated diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index d8c6c27a98..fdbdda695a 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -261,7 +261,7 @@ end ---@param err lsp.ResponseError? ---@param result lsp.CodeLens[] ---@param ctx lsp.HandlerContext -function M.on_codelens(err, result, ctx, _) +function M.on_codelens(err, result, ctx) if err then active_refreshes[assert(ctx.bufnr)] = nil log.error('codelens', err) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index c59e2db901..8fd30c7668 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -9,14 +9,6 @@ local augroup = api.nvim_create_augroup('vim_lsp_diagnostic', {}) local DEFAULT_CLIENT_ID = -1 -local function get_client_id(client_id) - if client_id == nil then - client_id = DEFAULT_CLIENT_ID - end - - return client_id -end - ---@param severity lsp.DiagnosticSeverity local function severity_lsp_to_vim(severity) if type(severity) == 'string' then @@ -218,8 +210,7 @@ end --- @param client_id? integer --- @param diagnostics vim.Diagnostic[] --- @param is_pull boolean ---- @param config? vim.diagnostic.Opts -local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config) +local function handle_diagnostics(uri, client_id, diagnostics, is_pull) local fname = vim.uri_to_fname(uri) if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then @@ -231,91 +222,39 @@ local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config) return end - client_id = get_client_id(client_id) - local namespace = M.get_namespace(client_id, is_pull) - - if config then - --- @cast config table<string, table> - for _, opt in pairs(config) do - convert_severity(opt) - end - -- Persist configuration to ensure buffer reloads use the same - -- configuration. To make lsp.with configuration work (See :help - -- lsp-handler-configuration) - vim.diagnostic.config(config, namespace) + if client_id == nil then + client_id = DEFAULT_CLIENT_ID end + local namespace = M.get_namespace(client_id, is_pull) + vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) end --- |lsp-handler| for the method "textDocument/publishDiagnostics" --- ---- See |vim.diagnostic.config()| for configuration options. Handler-specific ---- configuration can be set using |vim.lsp.with()|: ---- ---- ```lua ---- vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( ---- vim.lsp.diagnostic.on_publish_diagnostics, { ---- -- Enable underline, use default values ---- underline = true, ---- -- Enable virtual text, override spacing to 4 ---- virtual_text = { ---- spacing = 4, ---- }, ---- -- Use a function to dynamically turn signs off ---- -- and on, using buffer local variables ---- signs = function(namespace, bufnr) ---- return vim.b[bufnr].show_signs == true ---- end, ---- -- Disable a feature ---- update_in_insert = false, ---- } ---- ) ---- ``` +--- See |vim.diagnostic.config()| for configuration options. --- ---@param _ lsp.ResponseError? ---@param result lsp.PublishDiagnosticsParams ---@param ctx lsp.HandlerContext ----@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). -function M.on_publish_diagnostics(_, result, ctx, config) - handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false, config) +function M.on_publish_diagnostics(_, result, ctx) + handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false) end --- |lsp-handler| for the method "textDocument/diagnostic" --- ---- See |vim.diagnostic.config()| for configuration options. Handler-specific ---- configuration can be set using |vim.lsp.with()|: ---- ---- ```lua ---- vim.lsp.handlers["textDocument/diagnostic"] = vim.lsp.with( ---- vim.lsp.diagnostic.on_diagnostic, { ---- -- Enable underline, use default values ---- underline = true, ---- -- Enable virtual text, override spacing to 4 ---- virtual_text = { ---- spacing = 4, ---- }, ---- -- Use a function to dynamically turn signs off ---- -- and on, using buffer local variables ---- signs = function(namespace, bufnr) ---- return vim.b[bufnr].show_signs == true ---- end, ---- -- Disable a feature ---- update_in_insert = false, ---- } ---- ) ---- ``` +--- See |vim.diagnostic.config()| for configuration options. --- ---@param _ lsp.ResponseError? ---@param result lsp.DocumentDiagnosticReport ---@param ctx lsp.HandlerContext ----@param config vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). -function M.on_diagnostic(_, result, ctx, config) +function M.on_diagnostic(_, result, ctx) if result == nil or result.kind == 'unchanged' then return end - handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true, config) + handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true) end --- Clear push diagnostics and diagnostic cache. diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index ad827cfd34..2b7aefe0e1 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -5,10 +5,21 @@ local util = require('vim.lsp.util') local api = vim.api local completion = require('vim.lsp.completion') ---- @type table<string,lsp.Handler> +--- @type table<string, lsp.Handler> local M = {} --- FIXME: DOC: Expose in vimdocs +--- @deprecated +--- Client to server response handlers. +--- @type table<vim.lsp.protocol.Method.ClientToServer, lsp.Handler> +local RCS = {} + +--- Server to client request handlers. +--- @type table<vim.lsp.protocol.Method.ServerToClient, lsp.Handler> +local RSC = {} + +--- Server to client notification handlers. +--- @type table<vim.lsp.protocol.Method.ServerToClient, lsp.Handler> +local NSC = {} --- Writes to error buffer. ---@param ... string Will be concatenated before being written @@ -18,14 +29,15 @@ local function err_message(...) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand -M[ms.workspace_executeCommand] = function(_, _, _, _) +RCS[ms.workspace_executeCommand] = function(_, _, _) -- Error handling is done implicitly by wrapping all handlers; see end of this file end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress ---@param params lsp.ProgressParams ---@param ctx lsp.HandlerContext -M[ms.dollar_progress] = function(_, params, ctx) +---@diagnostic disable-next-line:no-unknown +RSC[ms.dollar_progress] = function(_, params, ctx) local client = vim.lsp.get_client_by_id(ctx.client_id) if not client then err_message('LSP[id=', tostring(ctx.client_id), '] client has shut down during progress update') @@ -59,26 +71,26 @@ M[ms.dollar_progress] = function(_, params, ctx) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create ----@param result lsp.WorkDoneProgressCreateParams +---@param params lsp.WorkDoneProgressCreateParams ---@param ctx lsp.HandlerContext -M[ms.window_workDoneProgress_create] = function(_, result, ctx) +RSC[ms.window_workDoneProgress_create] = function(_, params, ctx) local client = vim.lsp.get_client_by_id(ctx.client_id) if not client then err_message('LSP[id=', tostring(ctx.client_id), '] client has shut down during progress update') return vim.NIL end - client.progress:push(result) + client.progress:push(params) return vim.NIL end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest ----@param result lsp.ShowMessageRequestParams -M[ms.window_showMessageRequest] = function(_, result) - local actions = result.actions or {} +---@param params lsp.ShowMessageRequestParams +RSC[ms.window_showMessageRequest] = function(_, params) + local actions = params.actions or {} local co, is_main = coroutine.running() if co and not is_main then local opts = { - prompt = result.message .. ': ', + prompt = params.message .. ': ', format_item = function(action) return (action.title:gsub('\r\n', '\\r\\n')):gsub('\n', '\\n') end, @@ -92,7 +104,7 @@ M[ms.window_showMessageRequest] = function(_, result) end) return coroutine.yield() else - local option_strings = { result.message, '\nRequest Actions:' } + local option_strings = { params.message, '\nRequest Actions:' } for i, action in ipairs(actions) do local title = action.title:gsub('\r\n', '\\r\\n') title = title:gsub('\n', '\\n') @@ -108,19 +120,19 @@ M[ms.window_showMessageRequest] = function(_, result) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability ---- @param result lsp.RegistrationParams -M[ms.client_registerCapability] = function(_, result, ctx) +--- @param params lsp.RegistrationParams +RSC[ms.client_registerCapability] = function(_, params, ctx) local client_id = ctx.client_id local client = assert(vim.lsp.get_client_by_id(client_id)) - client.dynamic_capabilities:register(result.registrations) + client.dynamic_capabilities:register(params.registrations) for bufnr, _ in pairs(client.attached_buffers) do vim.lsp._set_defaults(client, bufnr) end ---@type string[] local unsupported = {} - for _, reg in ipairs(result.registrations) do + for _, reg in ipairs(params.registrations) do if reg.method == ms.workspace_didChangeWatchedFiles then vim.lsp._watchfiles.register(reg, ctx) elseif not client.dynamic_capabilities:supports_registration(reg.method) then @@ -139,13 +151,13 @@ M[ms.client_registerCapability] = function(_, result, ctx) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability ---- @param result lsp.UnregistrationParams -M[ms.client_unregisterCapability] = function(_, result, ctx) +--- @param params lsp.UnregistrationParams +RSC[ms.client_unregisterCapability] = function(_, params, ctx) local client_id = ctx.client_id local client = assert(vim.lsp.get_client_by_id(client_id)) - client.dynamic_capabilities:unregister(result.unregisterations) + client.dynamic_capabilities:unregister(params.unregisterations) - for _, unreg in ipairs(result.unregisterations) do + for _, unreg in ipairs(params.unregisterations) do if unreg.method == ms.workspace_didChangeWatchedFiles then vim.lsp._watchfiles.unregister(unreg, ctx) end @@ -153,20 +165,20 @@ M[ms.client_unregisterCapability] = function(_, result, ctx) return vim.NIL end +-- TODO(lewis6991): Do we need to notify other servers? --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit -M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) +RSC[ms.workspace_applyEdit] = function(_, params, ctx) assert( - workspace_edit, + params, 'workspace/applyEdit must be called with `ApplyWorkspaceEditParams`. Server is violating the specification' ) -- TODO(ashkan) Do something more with label? local client_id = ctx.client_id local client = assert(vim.lsp.get_client_by_id(client_id)) - if workspace_edit.label then - print('Workspace edit', workspace_edit.label) + if params.label then + print('Workspace edit', params.label) end - local status, result = - pcall(util.apply_workspace_edit, workspace_edit.edit, client.offset_encoding) + local status, result = pcall(util.apply_workspace_edit, params.edit, client.offset_encoding) return { applied = status, failureReason = result, @@ -182,8 +194,8 @@ local function lookup_section(table, section) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration ---- @param result lsp.ConfigurationParams -M[ms.workspace_configuration] = function(_, result, ctx) +--- @param params lsp.ConfigurationParams +RSC[ms.workspace_configuration] = function(_, params, ctx) local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) if not client then @@ -194,12 +206,12 @@ M[ms.workspace_configuration] = function(_, result, ctx) ) return end - if not result.items then + if not params.items then return {} end local response = {} - for _, item in ipairs(result.items) do + for _, item in ipairs(params.items) do if item.section then local value = lookup_section(client.settings, item.section) -- For empty sections with no explicit '' key, return settings as is @@ -216,7 +228,7 @@ M[ms.workspace_configuration] = function(_, result, ctx) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders -M[ms.workspace_workspaceFolders] = function(_, _, ctx) +RSC[ms.workspace_workspaceFolders] = function(_, _, ctx) local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) if not client then @@ -226,19 +238,22 @@ M[ms.workspace_workspaceFolders] = function(_, _, ctx) return client.workspace_folders or vim.NIL end -M[ms.textDocument_publishDiagnostics] = function(...) +NSC[ms.textDocument_publishDiagnostics] = function(...) return vim.lsp.diagnostic.on_publish_diagnostics(...) end -M[ms.textDocument_diagnostic] = function(...) +--- @private +RCS[ms.textDocument_diagnostic] = function(...) return vim.lsp.diagnostic.on_diagnostic(...) end -M[ms.textDocument_codeLens] = function(...) +--- @private +RCS[ms.textDocument_codeLens] = function(...) return vim.lsp.codelens.on_codelens(...) end -M[ms.textDocument_inlayHint] = function(...) +--- @private +RCS[ms.textDocument_inlayHint] = function(...) return vim.lsp.inlay_hint.on_inlayhint(...) end @@ -251,6 +266,7 @@ end ---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title ---@return lsp.Handler local function response_to_list(map_result, entity, title_fn) + --- @diagnostic disable-next-line:redundant-parameter return function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No ' .. entity .. ' found') @@ -274,8 +290,9 @@ local function response_to_list(map_result, entity, title_fn) end end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol -M[ms.textDocument_documentSymbol] = response_to_list( +RCS[ms.textDocument_documentSymbol] = response_to_list( util.symbols_to_items, 'document symbols', function(ctx) @@ -284,13 +301,15 @@ M[ms.textDocument_documentSymbol] = response_to_list( end ) +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol -M[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) +RCS[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) return string.format("Symbols matching '%s'", ctx.params.query) end) +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename -M[ms.textDocument_rename] = function(_, result, ctx, _) +RCS[ms.textDocument_rename] = function(_, result, ctx) if not result then vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO) return @@ -299,8 +318,9 @@ M[ms.textDocument_rename] = function(_, result, ctx, _) util.apply_workspace_edit(result, client.offset_encoding) end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting -M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) +RCS[ms.textDocument_rangeFormatting] = function(_, result, ctx) if not result then return end @@ -308,8 +328,9 @@ M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting -M[ms.textDocument_formatting] = function(_, result, ctx, _) +RCS[ms.textDocument_formatting] = function(_, result, ctx) if not result then return end @@ -319,7 +340,7 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion -M[ms.textDocument_completion] = function(_, result, _, _) +RCS[ms.textDocument_completion] = function(_, result, _) if vim.tbl_isempty(result or {}) then return end @@ -355,6 +376,7 @@ end --- - border: (default=nil) --- - Add borders to the floating window --- - See |vim.lsp.util.open_floating_preview()| for more options. +--- @diagnostic disable-next-line:redundant-parameter function M.hover(_, result, ctx, config) config = config or {} config.focus_id = ctx.method @@ -388,10 +410,11 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover --- @diagnostic disable-next-line: deprecated -M[ms.textDocument_hover] = M.hover +RCS[ms.textDocument_hover] = M.hover local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') +--- @deprecated remove in 0.13 --- |lsp-handler| for the method "textDocument/signatureHelp". --- --- The active parameter is highlighted with |hl-LspSignatureActiveParameter|. @@ -412,6 +435,7 @@ local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') --- - border: (default=nil) --- - Add borders to the floating window --- - See |vim.lsp.util.open_floating_preview()| for more options +--- @diagnostic disable-next-line:redundant-parameter function M.signature_help(_, result, ctx, config) config = config or {} config.focus_id = ctx.method @@ -452,11 +476,14 @@ function M.signature_help(_, result, ctx, config) return fbuf, fwin end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp -M[ms.textDocument_signatureHelp] = M.signature_help +--- @diagnostic disable-next-line:deprecated +RCS[ms.textDocument_signatureHelp] = M.signature_help +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight -M[ms.textDocument_documentHighlight] = function(_, result, ctx, _) +RCS[ms.textDocument_documentHighlight] = function(_, result, ctx) if not result then return end @@ -499,11 +526,13 @@ local function make_call_hierarchy_handler(direction) end end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls -M[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') +RCS[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls -M[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') +RCS[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') --- Displays type hierarchy in the quickfix window. local function make_type_hierarchy_handler() @@ -538,17 +567,19 @@ local function make_type_hierarchy_handler() end end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_incomingCalls -M[ms.typeHierarchy_subtypes] = make_type_hierarchy_handler() +RCS[ms.typeHierarchy_subtypes] = make_type_hierarchy_handler() +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_outgoingCalls -M[ms.typeHierarchy_supertypes] = make_type_hierarchy_handler() +RCS[ms.typeHierarchy_supertypes] = make_type_hierarchy_handler() --- @see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage ---- @param result lsp.LogMessageParams -M[ms.window_logMessage] = function(_, result, ctx, _) - local message_type = result.type - local message = result.message +--- @param params lsp.LogMessageParams +NSC['window/logMessage'] = function(_, params, ctx) + local message_type = params.type + local message = params.message local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) local client_name = client and client.name or string.format('id=%d', client_id) @@ -564,14 +595,14 @@ M[ms.window_logMessage] = function(_, result, ctx, _) else log.debug(message) end - return result + return params end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage ---- @param result lsp.ShowMessageParams -M[ms.window_showMessage] = function(_, result, ctx, _) - local message_type = result.type - local message = result.message +--- @param params lsp.ShowMessageParams +NSC['window/showMessage'] = function(_, params, ctx) + local message_type = params.type + local message = params.message local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) local client_name = client and client.name or string.format('id=%d', client_id) @@ -585,15 +616,16 @@ M[ms.window_showMessage] = function(_, result, ctx, _) local message_type_name = protocol.MessageType[message_type] api.nvim_out_write(string.format('LSP[%s][%s] %s\n', client_name, message_type_name, message)) end - return result + return params end +--- @private --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument ---- @param result lsp.ShowDocumentParams -M[ms.window_showDocument] = function(_, result, ctx, _) - local uri = result.uri +--- @param params lsp.ShowDocumentParams +RSC[ms.window_showDocument] = function(_, params, ctx) + local uri = params.uri - if result.external then + if params.external then -- TODO(lvimuser): ask the user for confirmation local cmd, err = vim.ui.open(uri) local ret = cmd and cmd:wait(2000) or nil @@ -621,35 +653,39 @@ M[ms.window_showDocument] = function(_, result, ctx, _) local location = { uri = uri, - range = result.selection, + range = params.selection, } local success = util.show_document(location, client.offset_encoding, { reuse_win = true, - focus = result.takeFocus, + focus = params.takeFocus, }) return { success = success or false } end ---@see https://microsoft.github.io/language-server-protocol/specification/#workspace_inlayHint_refresh -M[ms.workspace_inlayHint_refresh] = function(err, result, ctx, config) - return vim.lsp.inlay_hint.on_refresh(err, result, ctx, config) +RSC[ms.workspace_inlayHint_refresh] = function(err, result, ctx) + return vim.lsp.inlay_hint.on_refresh(err, result, ctx) end ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest -M[ms.workspace_semanticTokens_refresh] = function(err, result, ctx, _config) +RSC[ms.workspace_semanticTokens_refresh] = function(err, result, ctx) return vim.lsp.semantic_tokens._refresh(err, result, ctx) end +--- @nodoc +--- @type table<string, lsp.Handler> +M = vim.tbl_extend('force', M, RSC, NSC, RCS) + -- Add boilerplate error validation and logging for all of these. for k, fn in pairs(M) do + --- @diagnostic disable-next-line:redundant-parameter M[k] = function(err, result, ctx, config) if log.trace() then log.trace('default_handler', ctx.method, { err = err, result = result, ctx = vim.inspect(ctx), - config = config, }) end @@ -670,6 +706,7 @@ for k, fn in pairs(M) do return end + --- @diagnostic disable-next-line:redundant-parameter return fn(err, result, ctx, config) end end diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index e5892928cf..ca7bc3b022 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -37,7 +37,7 @@ local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {}) ---@param result lsp.InlayHint[]? ---@param ctx lsp.HandlerContext ---@private -function M.on_inlayhint(err, result, ctx, _) +function M.on_inlayhint(err, result, ctx) if err then log.error('inlayhint', err) return @@ -87,7 +87,7 @@ end --- |lsp-handler| for the method `workspace/inlayHint/refresh` ---@param ctx lsp.HandlerContext ---@private -function M.on_refresh(err, _, ctx, _) +function M.on_refresh(err, _, ctx) if err then return vim.NIL end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index b299a8438f..98965d0e20 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -619,9 +619,109 @@ function protocol.resolve_capabilities(server_capabilities) end -- Generated by gen_lsp.lua, keep at end of file. +--- @alias vim.lsp.protocol.Method.ClientToServer +--- | 'callHierarchy/incomingCalls', +--- | 'callHierarchy/outgoingCalls', +--- | 'codeAction/resolve', +--- | 'codeLens/resolve', +--- | 'completionItem/resolve', +--- | 'documentLink/resolve', +--- | '$/setTrace', +--- | 'exit', +--- | 'initialize', +--- | 'initialized', +--- | 'inlayHint/resolve', +--- | 'notebookDocument/didChange', +--- | 'notebookDocument/didClose', +--- | 'notebookDocument/didOpen', +--- | 'notebookDocument/didSave', +--- | 'shutdown', +--- | 'textDocument/codeAction', +--- | 'textDocument/codeLens', +--- | 'textDocument/colorPresentation', +--- | 'textDocument/completion', +--- | 'textDocument/declaration', +--- | 'textDocument/definition', +--- | 'textDocument/diagnostic', +--- | 'textDocument/didChange', +--- | 'textDocument/didClose', +--- | 'textDocument/didOpen', +--- | 'textDocument/didSave', +--- | 'textDocument/documentColor', +--- | 'textDocument/documentHighlight', +--- | 'textDocument/documentLink', +--- | 'textDocument/documentSymbol', +--- | 'textDocument/foldingRange', +--- | 'textDocument/formatting', +--- | 'textDocument/hover', +--- | 'textDocument/implementation', +--- | 'textDocument/inlayHint', +--- | 'textDocument/inlineCompletion', +--- | 'textDocument/inlineValue', +--- | 'textDocument/linkedEditingRange', +--- | 'textDocument/moniker', +--- | 'textDocument/onTypeFormatting', +--- | 'textDocument/prepareCallHierarchy', +--- | 'textDocument/prepareRename', +--- | 'textDocument/prepareTypeHierarchy', +--- | 'textDocument/rangeFormatting', +--- | 'textDocument/rangesFormatting', +--- | 'textDocument/references', +--- | 'textDocument/rename', +--- | 'textDocument/selectionRange', +--- | 'textDocument/semanticTokens/full', +--- | 'textDocument/semanticTokens/full/delta', +--- | 'textDocument/semanticTokens/range', +--- | 'textDocument/signatureHelp', +--- | 'textDocument/typeDefinition', +--- | 'textDocument/willSave', +--- | 'textDocument/willSaveWaitUntil', +--- | 'typeHierarchy/subtypes', +--- | 'typeHierarchy/supertypes', +--- | 'window/workDoneProgress/cancel', +--- | 'workspaceSymbol/resolve', +--- | 'workspace/diagnostic', +--- | 'workspace/didChangeConfiguration', +--- | 'workspace/didChangeWatchedFiles', +--- | 'workspace/didChangeWorkspaceFolders', +--- | 'workspace/didCreateFiles', +--- | 'workspace/didDeleteFiles', +--- | 'workspace/didRenameFiles', +--- | 'workspace/executeCommand', +--- | 'workspace/symbol', +--- | 'workspace/willCreateFiles', +--- | 'workspace/willDeleteFiles', +--- | 'workspace/willRenameFiles', + +--- @alias vim.lsp.protocol.Method.ServerToClient +--- | 'client/registerCapability', +--- | 'client/unregisterCapability', +--- | '$/logTrace', +--- | 'telemetry/event', +--- | 'textDocument/publishDiagnostics', +--- | 'window/logMessage', +--- | 'window/showDocument', +--- | 'window/showMessage', +--- | 'window/showMessageRequest', +--- | 'window/workDoneProgress/create', +--- | 'workspace/applyEdit', +--- | 'workspace/codeLens/refresh', +--- | 'workspace/configuration', +--- | 'workspace/diagnostic/refresh', +--- | 'workspace/foldingRange/refresh', +--- | 'workspace/inlayHint/refresh', +--- | 'workspace/inlineValue/refresh', +--- | 'workspace/semanticTokens/refresh', +--- | 'workspace/workspaceFolders', + +--- @alias vim.lsp.protocol.Method +--- | vim.lsp.protocol.Method.ClientToServer +--- | vim.lsp.protocol.Method.ServerToClient + +-- Generated by gen_lsp.lua, keep at end of file. --- ----@enum vim.lsp.protocol.Methods ----@see https://microsoft.github.io/language-server-protocol/specification/#metaModel +--- @enum vim.lsp.protocol.Methods +--- @see https://microsoft.github.io/language-server-protocol/specification/#metaModel --- LSP method names. protocol.Methods = { --- A request to resolve the incoming calls for a given `CallHierarchyItem`. diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua index c8dcf8c018..8afbae239a 100644 --- a/scripts/gen_lsp.lua +++ b/scripts/gen_lsp.lua @@ -58,14 +58,6 @@ end ---@param protocol vim._gen_lsp.Protocol local function gen_methods(protocol) - local output = { - '-- Generated by gen_lsp.lua, keep at end of file.', - '---', - '---@enum vim.lsp.protocol.Methods', - '---@see https://microsoft.github.io/language-server-protocol/specification/#metaModel', - '--- LSP method names.', - 'protocol.Methods = {', - } local indent = (' '):rep(2) --- @class vim._gen_lsp.Request @@ -98,6 +90,41 @@ local function gen_methods(protocol) table.sort(all, function(a, b) return to_luaname(a.method) < to_luaname(b.method) end) + + local output = { + '-- Generated by gen_lsp.lua, keep at end of file.', + '--- @alias vim.lsp.protocol.Method.ClientToServer', + } + for _, item in ipairs(all) do + if item.method and item.messageDirection == 'clientToServer' then + output[#output + 1] = ("--- | '%s',"):format(item.method) + end + end + + vim.list_extend(output, { + '', + '--- @alias vim.lsp.protocol.Method.ServerToClient', + }) + for _, item in ipairs(all) do + if item.method and item.messageDirection == 'serverToClient' then + output[#output + 1] = ("--- | '%s',"):format(item.method) + end + end + + vim.list_extend(output, { + '', + '--- @alias vim.lsp.protocol.Method', + '--- | vim.lsp.protocol.Method.ClientToServer', + '--- | vim.lsp.protocol.Method.ServerToClient', + '', + '-- Generated by gen_lsp.lua, keep at end of file.', + '---', + '--- @enum vim.lsp.protocol.Methods', + '--- @see https://microsoft.github.io/language-server-protocol/specification/#metaModel', + '--- LSP method names.', + 'protocol.Methods = {', + }) + for _, item in ipairs(all) do if item.method then if item.documentation then diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua index b7e292cad0..5afbe22793 100644 --- a/test/functional/plugin/lsp/diagnostic_spec.lua +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -120,85 +120,6 @@ describe('vim.lsp.diagnostic', function() end) describe('vim.lsp.diagnostic.on_publish_diagnostics', function() - it('allows configuring the virtual text via vim.lsp.with', function() - local expected_spacing = 10 - local extmarks = exec_lua(function() - _G.PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - virtual_text = { - spacing = expected_spacing, - }, - }) - - _G.PublishDiagnostics(nil, { - uri = fake_uri, - diagnostics = { - _G.make_error('Delayed Diagnostic', 4, 4, 4, 4), - }, - }, { client_id = client_id }) - - return _G.get_extmarks(diagnostic_bufnr, client_id) - end) - - local spacing = extmarks[1][4].virt_text[1][1] - - eq(expected_spacing, #spacing) - end) - - it('allows configuring the virtual text via vim.lsp.with using a function', function() - local expected_spacing = 10 - local extmarks = exec_lua(function() - _G.PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - virtual_text = function() - return { - spacing = expected_spacing, - } - end, - }) - - _G.PublishDiagnostics(nil, { - uri = fake_uri, - diagnostics = { - _G.make_error('Delayed Diagnostic', 4, 4, 4, 4), - }, - }, { client_id = client_id }) - - return _G.get_extmarks(diagnostic_bufnr, client_id) - end) - - local spacing = extmarks[1][4].virt_text[1][1] - - eq(expected_spacing, #spacing) - end) - - it('allows filtering via severity limit', function() - local get_extmark_count_with_severity = function(severity_limit) - return exec_lua(function() - _G.PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - underline = false, - virtual_text = { - severity = { min = severity_limit }, - }, - }) - - _G.PublishDiagnostics(nil, { - uri = fake_uri, - diagnostics = { - _G.make_warning('Delayed Diagnostic', 4, 4, 4, 4), - }, - }, { client_id = client_id }) - - return #_G.get_extmarks(diagnostic_bufnr, client_id) - end, client_id, fake_uri, severity_limit) - end - - -- No messages with Error or higher - eq(0, get_extmark_count_with_severity('ERROR')) - - -- But now we don't filter it - eq(1, get_extmark_count_with_severity('WARN')) - eq(1, get_extmark_count_with_severity('HINT')) - end) - it('correctly handles UTF-16 offsets', function() local line = 'All 💼 and no 🎉 makes Jack a dull 👦' local result = exec_lua(function() @@ -380,34 +301,6 @@ describe('vim.lsp.diagnostic', function() eq(1, diagnostics[1].severity) end) - it('allows configuring the virtual text via vim.lsp.with', function() - local expected_spacing = 10 - local extmarks = exec_lua(function() - _G.Diagnostic = vim.lsp.with(vim.lsp.diagnostic.on_diagnostic, { - virtual_text = { - spacing = expected_spacing, - }, - }) - - _G.Diagnostic(nil, { - kind = 'full', - items = { - _G.make_error('Pull Diagnostic', 4, 4, 4, 4), - }, - }, { - params = { - textDocument = { uri = fake_uri }, - }, - uri = fake_uri, - client_id = client_id, - }, {}) - - return _G.get_extmarks(diagnostic_bufnr, client_id) - end) - eq(2, #extmarks) - eq(expected_spacing, #extmarks[1][4].virt_text[1][1]) - end) - it('clears diagnostics when client detaches', function() exec_lua(function() vim.lsp.diagnostic.on_diagnostic(nil, { |