From f190f758ac58d9cc955368e047b070e0a2261033 Mon Sep 17 00:00:00 2001 From: Yinzuo Jiang Date: Sat, 20 Apr 2024 21:40:01 +0800 Subject: feat(lsp): add vim.lsp.buf.subtypes(), vim.lsp.buf.supertypes() (#28388) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mathias Fußenegger Co-authored-by: Maria José Solano --- runtime/lua/vim/lsp/buf.lua | 84 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'runtime/lua/vim/lsp/buf.lua') diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 17cc698b76..fa0cbab138 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -495,6 +495,90 @@ function M.outgoing_calls() call_hierarchy(ms.callHierarchy_outgoingCalls) end +--- @param method string +local function type_hierarchy(method) + --- Merge results from multiple clients into a single table. Client-ID is preserved. + --- + --- @param results table + local function merge_results(results) + local merged_results = {} + for client_id, client_result in pairs(results) do + if client_result.error then + vim.notify(client_result.error.message, vim.log.levels.WARN) + elseif client_result.result then + for _, item in pairs(client_result.result) do + table.insert(merged_results, { client_id, item }) + end + end + end + return merged_results + end + + local bufnr = api.nvim_get_current_buf() + local params = util.make_position_params() + --- @param results table + vim.lsp.buf_request_all(bufnr, ms.textDocument_prepareTypeHierarchy, params, function(results) + local merged_results = merge_results(results) + if #merged_results == 0 then + vim.notify('No items resolved', vim.log.levels.INFO) + return + end + + if #merged_results == 1 then + --- @type {integer, lsp.TypeHierarchyItem} + local item = merged_results[1] + local client = vim.lsp.get_client_by_id(item[1]) + if client then + --- @type lsp.TypeHierarchyItem + client.request(method, { item = item[2] }, nil, bufnr) + else + vim.notify( + string.format('Client with id=%d disappeared during call hierarchy request', item[1]), + vim.log.levels.WARN + ) + end + else + local opts = { + prompt = 'Select a type hierarchy item:', + kind = 'typehierarchy', + format_item = function(item) + if not item[2].detail or #item[2].detail == 0 then + return item[2].name + end + return string.format('%s %s', item[2].name, item[2].detail) + end, + } + + vim.ui.select(merged_results, opts, function(item) + local client = vim.lsp.get_client_by_id(item[1]) + if client then + --- @type lsp.TypeHierarchyItem + client.request(method, { item = item[2] }, nil, bufnr) + else + vim.notify( + string.format('Client with id=%d disappeared during call hierarchy request', item[1]), + vim.log.levels.WARN + ) + end + end) + end + end) +end + +--- Lists all the subtypes of the symbol under the +--- cursor in the |quickfix| window. If the symbol can resolve to +--- multiple items, the user can pick one using |vim.ui.select()|. +function M.subtypes() + type_hierarchy(ms.typeHierarchy_subtypes) +end + +--- Lists all the supertypes of the symbol under the +--- cursor in the |quickfix| window. If the symbol can resolve to +--- multiple items, the user can pick one using |vim.ui.select()|. +function M.supertypes() + type_hierarchy(ms.typeHierarchy_supertypes) +end + --- List workspace folders. --- function M.list_workspace_folders() -- cgit