summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorManuel <dev+git@manuelsbrain.de>2022-06-12 16:06:20 +0200
committerSimon Hauser <simon.hauser@helsinki-systems.de>2022-06-30 14:01:51 +0200
commit3a72cc89024120d09f32d70689cc9cbe367fc2b4 (patch)
tree8b51ae0442809616df1f26a16b4247d8771ef02d /lua
parentffcc2221d63aa89665e468be1dd8cd8e40e5f581 (diff)
feat(builtin.lsp): implement builtin handlers for lsp.(incoming|outgoing)_calls (#1484)
Fixes #863
Diffstat (limited to 'lua')
-rw-r--r--lua/telescope/builtin/init.lua12
-rw-r--r--lua/telescope/builtin/lsp.lua90
2 files changed, 100 insertions, 2 deletions
diff --git a/lua/telescope/builtin/init.lua b/lua/telescope/builtin/init.lua
index 7a3fb14..20d9812 100644
--- a/lua/telescope/builtin/init.lua
+++ b/lua/telescope/builtin/init.lua
@@ -378,6 +378,18 @@ builtin.jumplist = require_on_exported_call("telescope.builtin.internal").jumpli
---@field fname_width number: defines the width of the filename section (default: 30)
builtin.lsp_references = require_on_exported_call("telescope.builtin.lsp").references
+--- Lists LSP incoming calls for word under the cursor, jumps to reference on `<cr>`
+---@param opts table: options to pass to the picker
+---@field show_line boolean: show results text (default: true)
+---@field trim_text boolean: trim results text (default: false)
+builtin.lsp_incoming_calls = require_on_exported_call("telescope.builtin.lsp").incoming_calls
+
+--- Lists LSP outgoing calls for word under the cursor, jumps to reference on `<cr>`
+---@param opts table: options to pass to the picker
+---@field show_line boolean: show results text (default: true)
+---@field trim_text boolean: trim results text (default: false)
+builtin.lsp_outgoing_calls = require_on_exported_call("telescope.builtin.lsp").outgoing_calls
+
--- Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope
---@param opts table: options to pass to the picker
---@field jump_type string: how to goto definition if there is only one, values: "tab", "split", "vsplit", "never"
diff --git a/lua/telescope/builtin/lsp.lua b/lua/telescope/builtin/lsp.lua
index 410a068..85fabb0 100644
--- a/lua/telescope/builtin/lsp.lua
+++ b/lua/telescope/builtin/lsp.lua
@@ -52,9 +52,93 @@ lsp.references = function(opts)
end)
end
-local function list_or_jump(action, title, opts)
- opts = opts or {}
+local function call_hierarchy(opts, method, title, direction, item)
+ vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
+ if err then
+ vim.api.nvim_err_writeln("Error handling " .. title .. ": " .. err)
+ return
+ end
+
+ if not result or vim.tbl_isempty(result) then
+ return
+ end
+
+ local locations = {}
+ for _, ch_call in pairs(result) do
+ local ch_item = ch_call[direction]
+ for _, range in pairs(ch_call.fromRanges) do
+ table.insert(locations, {
+ filename = vim.uri_to_fname(ch_item.uri),
+ text = ch_item.name,
+ lnum = range.start.line + 1,
+ col = range.start.character + 1,
+ })
+ end
+ end
+
+ pickers.new(opts, {
+ prompt_title = title,
+ finder = finders.new_table {
+ results = locations,
+ entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
+ },
+ previewer = conf.qflist_previewer(opts),
+ sorter = conf.generic_sorter(opts),
+ push_cursor_on_edit = true,
+ push_tagstack_on_edit = true,
+ }):find()
+ end)
+end
+
+local function pick_call_hierarchy_item(call_hierarchy_items)
+ if not call_hierarchy_items then
+ return
+ end
+ 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 choice
+end
+
+local function calls(opts, direction)
+ local params = vim.lsp.util.make_position_params()
+ vim.lsp.buf_request(opts.bufnr, "textDocument/prepareCallHierarchy", params, function(err, result)
+ if err then
+ vim.api.nvim_err_writeln("Error when preparing call hierarchy: " .. err)
+ return
+ end
+
+ local call_hierarchy_item = pick_call_hierarchy_item(result)
+ if not call_hierarchy_item then
+ return
+ end
+
+ if direction == "from" then
+ call_hierarchy(opts, "callHierarchy/incomingCalls", "LSP Incoming Calls", direction, call_hierarchy_item)
+ else
+ call_hierarchy(opts, "callHierarchy/outgoingCalls", "LSP Outgoing Calls", direction, call_hierarchy_item)
+ end
+ end)
+end
+
+lsp.incoming_calls = function(opts)
+ calls(opts, "from")
+end
+lsp.outgoing_calls = function(opts)
+ calls(opts, "to")
+end
+
+local function list_or_jump(action, title, opts)
local params = vim.lsp.util.make_position_params(opts.winnr)
vim.lsp.buf_request(opts.bufnr, action, params, function(err, result, ctx, _)
if err then
@@ -271,6 +355,8 @@ local feature_map = {
["type_definitions"] = "typeDefinitionProvider",
["implementations"] = "implementationProvider",
["workspace_symbols"] = "workspaceSymbolProvider",
+ ["incoming_calls"] = "callHierarchyProvider",
+ ["outgoing_calls"] = "callHierarchyProvider",
}
local function apply_checks(mod)