aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/buf.lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/lsp/buf.lua')
-rw-r--r--runtime/lua/vim/lsp/buf.lua139
1 files changed, 72 insertions, 67 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 7bf3565499..fc41246588 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -569,6 +569,23 @@ function M.document_symbol(opts)
request_with_opts(ms.textDocument_documentSymbol, params, opts)
end
+--- @param client_id integer
+--- @param method string
+--- @param params table
+--- @param handler? lsp.Handler
+--- @param bufnr? integer
+local function request_with_id(client_id, method, params, handler, bufnr)
+ local client = vim.lsp.get_client_by_id(client_id)
+ if not client then
+ vim.notify(
+ string.format('Client with id=%d disappeared during call hierarchy request', client_id),
+ vim.log.levels.WARN
+ )
+ return
+ end
+ client.request(method, params, handler, bufnr)
+end
+
--- @param call_hierarchy_items lsp.CallHierarchyItem[]
--- @return lsp.CallHierarchyItem?
local function pick_call_hierarchy_item(call_hierarchy_items)
@@ -600,19 +617,11 @@ local function call_hierarchy(method)
vim.notify('No item resolved', vim.log.levels.WARN)
return
end
- local call_hierarchy_item = pick_call_hierarchy_item(result)
- if not call_hierarchy_item then
+ local item = pick_call_hierarchy_item(result)
+ if not item then
return
end
- local client = vim.lsp.get_client_by_id(ctx.client_id)
- if client then
- client.request(method, { item = call_hierarchy_item }, nil, ctx.bufnr)
- else
- vim.notify(
- string.format('Client with id=%d disappeared during call hierarchy request', ctx.client_id),
- vim.log.levels.WARN
- )
- end
+ request_with_id(ctx.client_id, method, { item = item }, nil, ctx.bufnr)
end)
end
@@ -630,78 +639,74 @@ function M.outgoing_calls()
call_hierarchy(ms.callHierarchy_outgoingCalls)
end
+--- @param item lsp.TypeHierarchyItem
+local function format_type_hierarchy_item(item)
+ if not item.detail or #item.detail == 0 then
+ return item.name
+ end
+ return string.format('%s %s', item.name, item.detail)
+end
+
--- Lists all the subtypes or 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()|.
---@param kind "subtypes"|"supertypes"
function M.typehierarchy(kind)
local method = kind == 'subtypes' and ms.typeHierarchy_subtypes or ms.typeHierarchy_supertypes
-
- --- Merge results from multiple clients into a single table. Client-ID is preserved.
- ---
- --- @param results table<integer, {error: lsp.ResponseError?, result: lsp.TypeHierarchyItem[]?}>
- --- @return [integer, lsp.TypeHierarchyItem][]
- 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
+ local bufnr = api.nvim_get_current_buf()
+ local clients = vim.lsp.get_clients({ bufnr = bufnr, method = method })
+ if not next(clients) then
+ vim.notify(vim.lsp._unsupported_method(method), vim.log.levels.WARN)
+ return
end
- local bufnr = api.nvim_get_current_buf()
- local params = util.make_position_params()
- --- @param results table<integer, {error: lsp.ResponseError?, result: lsp.TypeHierarchyItem[]?}>
- 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
+ local win = api.nvim_get_current_win()
- if #merged_results == 1 then
- local item = merged_results[1]
- local client = vim.lsp.get_client_by_id(item[1])
- if client then
- 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
+ --- @param results [integer, lsp.TypeHierarchyItem][]
+ local function on_response(results)
+ if #results == 0 then
+ vim.notify('No items resolved', vim.log.levels.INFO)
+ elseif #results == 1 then
+ local client_id, item = results[1][1], results[1][2]
+ request_with_id(client_id, method, { item = item }, nil, bufnr)
else
- local select_opts = {
+ vim.ui.select(results, {
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)
+ format_item = function(x)
+ return format_type_hierarchy_item(x[2])
end,
- }
-
- vim.ui.select(merged_results, select_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
- )
+ }, function(x)
+ if x then
+ local client_id, item = x[1], x[2]
+ request_with_id(client_id, method, { item = item }, nil, bufnr)
end
end)
end
- end)
+ end
+
+ local results = {} --- @type [integer, lsp.TypeHierarchyItem][]
+
+ local remaining = #clients
+
+ for _, client in ipairs(clients) do
+ local params = util.make_position_params(win, client.offset_encoding)
+ client.request(method, params, function(err, result, ctx)
+ --- @cast result lsp.TypeHierarchyItem[]?
+ if err then
+ vim.notify(err.message, vim.log.levels.WARN)
+ elseif result then
+ for _, item in pairs(result) do
+ results[#results + 1] = { ctx.client_id, item }
+ end
+ end
+
+ remaining = remaining - 1
+ if remaining == 0 then
+ on_response(results)
+ end
+ end, bufnr)
+ end
end
--- List workspace folders.