aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2024-10-24 11:20:27 +0100
committerLewis Russell <me@lewisr.dev>2024-10-24 13:15:25 +0100
commit39d79efa1e1e1e5c3476dee54cc2bc4abc725a8f (patch)
tree121612b8f3498071645193b6cb750d8d76a9cd1e
parentc8d7d65679f832b406eb551411721cf21bae52bb (diff)
downloadrneovim-39d79efa1e1e1e5c3476dee54cc2bc4abc725a8f.tar.gz
rneovim-39d79efa1e1e1e5c3476dee54cc2bc4abc725a8f.tar.bz2
rneovim-39d79efa1e1e1e5c3476dee54cc2bc4abc725a8f.zip
fix(lsp): better multi-client support for callHierarchy
Only ever display a dialogue box once. Switch from vim.fn.inpulist to vim.ui.select refactor(lsp): merge call and type hierarchy functions
-rw-r--r--runtime/lua/vim/lsp/buf.lua130
1 files changed, 53 insertions, 77 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index e0c03edf1e..f2d5d204f4 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -584,7 +584,7 @@ local function request_with_id(client_id, method, params, handler, bufnr)
local client = 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),
+ string.format('Client with id=%d disappeared during hierarchy request', client_id),
vim.log.levels.WARN
)
return
@@ -592,80 +592,33 @@ local function request_with_id(client_id, method, params, handler, bufnr)
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)
- if #call_hierarchy_items == 1 then
- return call_hierarchy_items[1]
- end
- local items = {}
- for i, item in pairs(call_hierarchy_items) do
- local entry = item.detail or item.name
- table.insert(items, string.format('%d. %s', i, entry))
- end
- local choice = vim.fn.inputlist(items)
- if choice < 1 or choice > #items then
- return
- end
- return call_hierarchy_items[choice]
-end
-
---- @param method string
-local function call_hierarchy(method)
- lsp.buf_request(
- 0,
- ms.textDocument_prepareCallHierarchy,
- client_positional_params(),
- --- @param result lsp.CallHierarchyItem[]?
- function(err, result, ctx)
- if err then
- vim.notify(err.message, vim.log.levels.WARN)
- return
- end
- if not result or vim.tbl_isempty(result) then
- vim.notify('No item resolved', vim.log.levels.WARN)
- return
- end
- local item = pick_call_hierarchy_item(result)
- if not item then
- return
- end
- request_with_id(ctx.client_id, method, { item = item }, nil, ctx.bufnr)
- end
- )
-end
-
---- Lists all the call sites of the symbol under the cursor in the
---- |quickfix| window. If the symbol can resolve to multiple
---- items, the user can pick one in the |inputlist()|.
-function M.incoming_calls()
- call_hierarchy(ms.callHierarchy_incomingCalls)
-end
-
---- Lists all the items that are called by the symbol under the
---- cursor in the |quickfix| window. If the symbol can resolve to
---- multiple items, the user can pick one in the |inputlist()|.
-function M.outgoing_calls()
- call_hierarchy(ms.callHierarchy_outgoingCalls)
-end
-
---- @param item lsp.TypeHierarchyItem
-local function format_type_hierarchy_item(item)
+--- @param item lsp.TypeHierarchyItem|lsp.CallHierarchyItem
+local function format_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
- local pmethod = ms.textDocument_prepareTypeHierarchy
+local hierarchy_methods = {
+ [ms.typeHierarchy_subtypes] = 'type',
+ [ms.typeHierarchy_supertypes] = 'type',
+ [ms.callHierarchy_incomingCalls] = 'call',
+ [ms.callHierarchy_outgoingCalls] = 'call',
+}
+
+--- @param method string
+local function hierarchy(method)
+ local kind = hierarchy_methods[method]
+ if not kind then
+ error('unsupported method ' .. method)
+ end
+
+ local prepare_method = kind == 'type' and ms.textDocument_prepareTypeHierarchy
+ or ms.textDocument_prepareCallHierarchy
+
local bufnr = api.nvim_get_current_buf()
- local clients = lsp.get_clients({ bufnr = bufnr, method = pmethod })
+ local clients = lsp.get_clients({ bufnr = bufnr, method = prepare_method })
if not next(clients) then
vim.notify(lsp._unsupported_method(method), vim.log.levels.WARN)
return
@@ -673,19 +626,19 @@ function M.typehierarchy(kind)
local win = api.nvim_get_current_win()
- --- @param results [integer, lsp.TypeHierarchyItem][]
+ --- @param results [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][]
local function on_response(results)
if #results == 0 then
- vim.notify('No items resolved', vim.log.levels.INFO)
+ vim.notify('No item resolved', vim.log.levels.WARN)
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
vim.ui.select(results, {
- prompt = 'Select a type hierarchy item:',
- kind = 'typehierarchy',
+ prompt = string.format('Select a %s hierarchy item:', kind),
+ kind = kind .. 'hierarchy',
format_item = function(x)
- return format_type_hierarchy_item(x[2])
+ return format_hierarchy_item(x[2])
end,
}, function(x)
if x then
@@ -696,18 +649,18 @@ function M.typehierarchy(kind)
end
end
- local results = {} --- @type [integer, lsp.TypeHierarchyItem][]
+ local results = {} --- @type [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][]
local remaining = #clients
for _, client in ipairs(clients) do
local params = util.make_position_params(win, client.offset_encoding)
- client.request(pmethod, params, function(err, result, ctx)
- --- @cast result lsp.TypeHierarchyItem[]?
+ --- @param result lsp.CallHierarchyItem[]|lsp.TypeHierarchyItem[]?
+ client.request(prepare_method, params, function(err, result, ctx)
if err then
vim.notify(err.message, vim.log.levels.WARN)
elseif result then
- for _, item in pairs(result) do
+ for _, item in ipairs(result) do
results[#results + 1] = { ctx.client_id, item }
end
end
@@ -720,6 +673,29 @@ function M.typehierarchy(kind)
end
end
+--- Lists all the call sites of the symbol under the cursor in the
+--- |quickfix| window. If the symbol can resolve to multiple
+--- items, the user can pick one in the |inputlist()|.
+function M.incoming_calls()
+ hierarchy(ms.callHierarchy_incomingCalls)
+end
+
+--- Lists all the items that are called by the symbol under the
+--- cursor in the |quickfix| window. If the symbol can resolve to
+--- multiple items, the user can pick one in the |inputlist()|.
+function M.outgoing_calls()
+ hierarchy(ms.callHierarchy_outgoingCalls)
+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
+ hierarchy(method)
+end
+
--- List workspace folders.
---
function M.list_workspace_folders()