neovim

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

commit d7e0d46ffa8f9f1eaf27f8b7ee32ef9a21cb9b84
parent 34b4df774d4fb5653422d6a1c1e730ef8565a315
Author: Lewis Russell <lewis6991@gmail.com>
Date:   Thu, 17 Apr 2025 10:21:41 +0100

feat(lsp): use stricter types for methods

This change modifies gen_lsp.lua so alias types are generated for
various types of lsp methods to distinguish between notifications
and requests:
 - vim.lsp.protocol.Method.ServerToClient.Request
 - vim.lsp.protocol.Method.ServerToClient.Notification
 - vim.lsp.protocol.Method.ClientToServer.Request
 - vim.lsp.protocol.Method.ClientToServer.Notification

 These types are then used instead of `string` where appropriate.

Diffstat:
Mruntime/lua/vim/lsp.lua | 2+-
Mruntime/lua/vim/lsp/_meta/protocol.lua | 4++--
Mruntime/lua/vim/lsp/buf.lua | 6+++---
Mruntime/lua/vim/lsp/client.lua | 30+++++++-----------------------
Mruntime/lua/vim/lsp/protocol.lua | 64++++++++++++++++++++++++++++++++++++++--------------------------
Mruntime/lua/vim/lsp/util.lua | 2+-
Msrc/gen/gen_lsp.lua | 95++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/gen/gen_vimdoc.lua | 3+++
8 files changed, 103 insertions(+), 103 deletions(-)

diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua @@ -1285,7 +1285,7 @@ end ---@since 7 --- ---@param bufnr integer Buffer handle, or 0 for current. ----@param method string LSP method name +---@param method vim.lsp.protocol.Method.ClientToServer.Request LSP method name ---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server. --- Can also be passed as a function that returns the params table for cases where --- parameters are specific to the client. diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -1,11 +1,11 @@ --[[ -THIS FILE IS GENERATED by scripts/gen_lsp.lua +THIS FILE IS GENERATED by scr/gen/gen_lsp.lua DO NOT EDIT MANUALLY Based on LSP protocol 3.18 Regenerate: -nvim -l scripts/gen_lsp.lua gen --version 3.18 +nvim -l scr/gen/gen_lsp.lua gen --version 3.18 --]] ---@meta diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua @@ -158,7 +158,7 @@ local function request_with_opts(name, params, opts) lsp.buf_request(0, name, params, req_handler) end ----@param method string +---@param method vim.lsp.protocol.Method.ClientToServer.Request ---@param opts? vim.lsp.LocationOpts local function get_locations(method, opts) opts = opts or {} @@ -814,7 +814,7 @@ function M.document_symbol(opts) end --- @param client_id integer ---- @param method string +--- @param method vim.lsp.protocol.Method.ClientToServer.Request --- @param params table --- @param handler? lsp.Handler --- @param bufnr? integer @@ -845,7 +845,7 @@ local hierarchy_methods = { [ms.callHierarchy_outgoingCalls] = 'call', } ---- @param method string +--- @param method vim.lsp.protocol.Method.ClientToServer.Request local function hierarchy(method) local kind = hierarchy_methods[method] if not kind then diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua @@ -656,7 +656,7 @@ end --- This is a thin wrapper around {client.rpc.request} with some additional --- checks for capabilities and handler availability. --- ---- @param method string LSP method name. +--- @param method vim.lsp.protocol.Method.ClientToServer.Request LSP method name. --- @param params? table LSP request params. --- @param handler? lsp.Handler Response |lsp-handler| for this method. --- @param bufnr? integer (default: 0) Buffer handle, or 0 for current. @@ -721,7 +721,7 @@ end --- --- This is a wrapper around |Client:request()| --- ---- @param method string LSP method name. +--- @param method vim.lsp.protocol.Method.ClientToServer.Request LSP method name. --- @param params table LSP request params. --- @param timeout_ms integer? Maximum time in milliseconds to wait for --- a result. Defaults to 1000 @@ -757,7 +757,7 @@ end --- Sends a notification to an LSP server. --- ---- @param method string LSP method name. +--- @param method vim.lsp.protocol.Method.ClientToServer.Notification LSP method name. --- @param params table? LSP request params. --- @return boolean status indicating if the notification was successful. --- If it is false, then the client has shutdown. @@ -828,7 +828,7 @@ function Client:stop(force) end --- Get options for a method that is registered dynamically. ---- @param method string +--- @param method vim.lsp.protocol.Method function Client:_supports_registration(method) local capability = vim.tbl_get(self.capabilities, unpack(vim.split(method, '/'))) return type(capability) == 'table' and capability.dynamicRegistration @@ -901,7 +901,7 @@ function Client:_get_language_id(bufnr) return self.get_language_id(bufnr, vim.bo[bufnr].filetype) end ---- @param method string +--- @param method vim.lsp.protocol.Method --- @param bufnr? integer --- @return lsp.Registration? function Client:_get_registration(method, bufnr) @@ -1051,7 +1051,7 @@ end --- Always returns true for unknown off-spec methods. --- --- Note: Some language server capabilities can be file specific. ---- @param method string +--- @param method vim.lsp.protocol.Method.ClientToServer --- @param bufnr? integer function Client:supports_method(method, bufnr) -- Deprecated form @@ -1082,27 +1082,11 @@ function Client:supports_method(method, bufnr) return false end ---- Get options for a method that is registered dynamically. ---- @param method string ---- @param bufnr? integer ---- @return lsp.LSPAny? -function Client:_get_registration_options(method, bufnr) - if not self:_supports_registration(method) then - return - end - - local reg = self:_get_registration(method, bufnr) - - if reg then - return reg.registerOptions - end -end - --- @private --- Handles a notification sent by an LSP server by invoking the --- corresponding handler. --- ---- @param method string LSP method name +--- @param method vim.lsp.protocol.Method.ServerToClient.Notification LSP method name --- @param params table The parameters for that method. function Client:_notification(method, params) log.trace('notification', method, params) diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua @@ -621,22 +621,15 @@ function protocol.resolve_capabilities(server_capabilities) end -- Generated by gen_lsp.lua, keep at end of file. ---- @alias vim.lsp.protocol.Method.ClientToServer +--- @alias vim.lsp.protocol.Method.ClientToServer.Request --- | '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', @@ -645,10 +638,6 @@ end --- | 'textDocument/declaration', --- | 'textDocument/definition', --- | 'textDocument/diagnostic', ---- | 'textDocument/didChange', ---- | 'textDocument/didClose', ---- | 'textDocument/didOpen', ---- | 'textDocument/didSave', --- | 'textDocument/documentColor', --- | 'textDocument/documentHighlight', --- | 'textDocument/documentLink', @@ -676,19 +665,11 @@ end --- | '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/textDocumentContent', @@ -696,15 +677,35 @@ end --- | 'workspace/willDeleteFiles', --- | 'workspace/willRenameFiles', ---- @alias vim.lsp.protocol.Method.ServerToClient +--- @alias vim.lsp.protocol.Method.ClientToServer.Notification +--- | '$/setTrace', +--- | 'exit', +--- | 'initialized', +--- | 'notebookDocument/didChange', +--- | 'notebookDocument/didClose', +--- | 'notebookDocument/didOpen', +--- | 'notebookDocument/didSave', +--- | 'textDocument/didChange', +--- | 'textDocument/didClose', +--- | 'textDocument/didOpen', +--- | 'textDocument/didSave', +--- | 'textDocument/willSave', +--- | 'window/workDoneProgress/cancel', +--- | 'workspace/didChangeConfiguration', +--- | 'workspace/didChangeWatchedFiles', +--- | 'workspace/didChangeWorkspaceFolders', +--- | 'workspace/didCreateFiles', +--- | 'workspace/didDeleteFiles', +--- | 'workspace/didRenameFiles', + +--- @alias vim.lsp.protocol.Method.ClientToServer +--- | vim.lsp.protocol.Method.ClientToServer.Request +--- | vim.lsp.protocol.Method.ClientToServer.Notification + +--- @alias vim.lsp.protocol.Method.ServerToClient.Request --- | 'client/registerCapability', --- | 'client/unregisterCapability', ---- | '$/logTrace', ---- | 'telemetry/event', ---- | 'textDocument/publishDiagnostics', ---- | 'window/logMessage', --- | 'window/showDocument', ---- | 'window/showMessage', --- | 'window/showMessageRequest', --- | 'window/workDoneProgress/create', --- | 'workspace/applyEdit', @@ -718,6 +719,17 @@ end --- | 'workspace/textDocumentContent/refresh', --- | 'workspace/workspaceFolders', +--- @alias vim.lsp.protocol.Method.ServerToClient.Notification +--- | '$/logTrace', +--- | 'telemetry/event', +--- | 'textDocument/publishDiagnostics', +--- | 'window/logMessage', +--- | 'window/showMessage', + +--- @alias vim.lsp.protocol.Method.ServerToClient +--- | vim.lsp.protocol.Method.ServerToClient.Request +--- | vim.lsp.protocol.Method.ServerToClient.Notification + --- @alias vim.lsp.protocol.Method --- | vim.lsp.protocol.Method.ClientToServer --- | vim.lsp.protocol.Method.ServerToClient diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua @@ -2164,7 +2164,7 @@ end ---@class (private) vim.lsp.util._cancel_requests.Filter ---@field bufnr? integer ---@field clients? vim.lsp.Client[] ----@field method? string +---@field method? vim.lsp.protocol.Method.ClientToServer.Request ---@field type? string ---@private diff --git a/src/gen/gen_lsp.lua b/src/gen/gen_lsp.lua @@ -33,6 +33,24 @@ end --- @field enumerations vim._gen_lsp.Enumeration[] --- @field typeAliases vim._gen_lsp.TypeAlias[] +--- @class vim._gen_lsp.Notification +--- @field deprecated? string +--- @field documentation? string +--- @field messageDirection string +--- @field clientCapability? string +--- @field serverCapability? string +--- @field method string +--- @field params? any +--- @field proposed? boolean +--- @field registrationMethod? string +--- @field registrationOptions? any +--- @field since? string + +--- @class vim._gen_lsp.Request : vim._gen_lsp.Notification +--- @field errorData? any +--- @field partialResult? any +--- @field result any + ---@param opt vim._gen_lsp.opt ---@return vim._gen_lsp.Protocol local function read_json(opt) @@ -66,64 +84,47 @@ local function write_to_protocol(protocol, gen_methods, gen_capabilities) local indent = (' '):rep(2) - --- @class vim._gen_lsp.Request - --- @field deprecated? string - --- @field documentation? string - --- @field messageDirection string - --- @field clientCapability? string - --- @field serverCapability? string - --- @field method string - --- @field params? any - --- @field proposed? boolean - --- @field registrationMethod? string - --- @field registrationOptions? any - --- @field since? string - - --- @class vim._gen_lsp.Notification - --- @field deprecated? string - --- @field documentation? string - --- @field errorData? any - --- @field messageDirection string - --- @field clientCapability? string - --- @field serverCapability? string - --- @field method string - --- @field params? any[] - --- @field partialResult? any - --- @field proposed? boolean - --- @field registrationMethod? string - --- @field registrationOptions? any - --- @field result any - --- @field since? string + local function compare_method(a, b) + return to_luaname(a.method) < to_luaname(b.method) + end ---@type (vim._gen_lsp.Request|vim._gen_lsp.Notification)[] - local all = vim.list_extend(protocol.requests, protocol.notifications) - table.sort(all, function(a, b) - return to_luaname(a.method) < to_luaname(b.method) - end) + local all = {} + vim.list_extend(all, protocol.notifications) + vim.list_extend(all, protocol.requests) + + table.sort(all, compare_method) + table.sort(protocol.requests, compare_method) + table.sort(protocol.notifications, compare_method) local output = { '-- Generated by gen_lsp.lua, keep at end of file.' } if gen_methods then - output[#output + 1] = '--- @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) + for _, dir in ipairs({ 'clientToServer', 'serverToClient' }) do + local dir1 = dir:sub(1, 1):upper() .. dir:sub(2) + local alias = ('vim.lsp.protocol.Method.%s'):format(dir1) + for _, b in ipairs({ + { title = 'Request', methods = protocol.requests }, + { title = 'Notification', methods = protocol.notifications }, + }) do + output[#output + 1] = ('--- @alias %s.%s'):format(alias, b.title) + for _, item in ipairs(b.methods) do + if item.messageDirection == dir then + output[#output + 1] = ("--- | '%s',"):format(item.method) + end + end + output[#output + 1] = '' 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 + vim.list_extend(output, { + ('--- @alias %s'):format(alias), + ('--- | %s.Request'):format(alias), + ('--- | %s.Notification'):format(alias), + '', + }) end vim.list_extend(output, { - '', '--- @alias vim.lsp.protocol.Method', '--- | vim.lsp.protocol.Method.ClientToServer', '--- | vim.lsp.protocol.Method.ServerToClient', diff --git a/src/gen/gen_vimdoc.lua b/src/gen/gen_vimdoc.lua @@ -427,6 +427,9 @@ end --- @param generics? table<string,string> --- @param default? string local function render_type(ty, generics, default) + -- TODO(lewis6991): Document LSP protocol types + ty = ty:gsub('vim%.lsp%.protocol%.Method.[%w.]+', 'string') + if generics then ty = replace_generics(ty, generics) end