From 52dedd28d8ca325cb3e4cf65ef52915b5be238eb Mon Sep 17 00:00:00 2001 From: bhagwan Date: Sat, 30 Apr 2022 11:25:48 -0700 Subject: [PATCH] feat(lsp): added 'lsp_(incoming|outgoing)_calls' (closes #399) --- README.md | 2 ++ doc/fzf-lua.txt | 2 ++ lua/fzf-lua/init.lua | 1 + lua/fzf-lua/providers/lsp.lua | 65 +++++++++++++++++++++++++++++++---- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cb7fd44..86b9b5b 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,8 @@ vim.api.nvim_set_keymap('n', '', | `lsp_code_actions` | Code Actions | | `lsp_document_diagnostics` | Document Diagnostics | | `lsp_workspace_diagnostics` | Workspace Diagnostics | +| `lsp_incoming_calls` | Incoming Calls | +| `lsp_outgoing_calls` | Outgoing Calls | ### Misc | Command | List | diff --git a/doc/fzf-lua.txt b/doc/fzf-lua.txt index 41f642a..a2709a2 100644 --- a/doc/fzf-lua.txt +++ b/doc/fzf-lua.txt @@ -227,6 +227,8 @@ LSP *fzf-lua-lsp* | `lsp_code_actions` | Code Actions | | `lsp_document_diagnostics` | Document Diagnostics | | `lsp_workspace_diagnostics` | Workspace Diagnostics | +| `lsp_incoming_calls` | Incoming Calls | +| `lsp_outgoing_calls` | Outgoing Calls | diff --git a/lua/fzf-lua/init.lua b/lua/fzf-lua/init.lua index 75aadf3..d305a49 100644 --- a/lua/fzf-lua/init.lua +++ b/lua/fzf-lua/init.lua @@ -140,6 +140,7 @@ M.lsp_code_actions = require'fzf-lua.providers.lsp'.code_actions M.lsp_document_diagnostics = require'fzf-lua.providers.lsp'.diagnostics M.lsp_workspace_diagnostics = require'fzf-lua.providers.lsp'.workspace_diagnostics M.lsp_incoming_calls = require'fzf-lua.providers.lsp'.incoming_calls +M.lsp_outgoing_calls = require'fzf-lua.providers.lsp'.outgoing_calls M.register_ui_select = require'fzf-lua.providers.ui_select'.register M.deregister_ui_select = require'fzf-lua.providers.ui_select'.deregister diff --git a/lua/fzf-lua/providers/lsp.lua b/lua/fzf-lua/providers/lsp.lua index 5340338..de257b7 100644 --- a/lua/fzf-lua/providers/lsp.lua +++ b/lua/fzf-lua/providers/lsp.lua @@ -50,6 +50,28 @@ local function location_handler(opts, cb, _, result, ctx, _) end end +local function call_hierarchy_handler(opts, cb, _, result, _, _) + for _, call_hierarchy_call in pairs(result) do + --- "from" for incoming calls and "to" for outgoing calls + local call_hierarchy_item = call_hierarchy_call.from or call_hierarchy_call.to + for _, range in pairs(call_hierarchy_call.fromRanges) do + local entry = { + filename = assert(vim.uri_to_fname(call_hierarchy_item.uri)), + text = call_hierarchy_item.name, + lnum = range.start.line + 1, + col = range.start.character + 1, + } + entry = core.make_entry_lcol(opts, entry) + entry = core.make_entry_file(opts, entry) + if entry then + cb(entry, function(err) + if err then return end + end) + end + end + end +end + local function symbol_handler(opts, cb, _, result, _, _) result = vim.tbl_islist(result) and result or {result} local items = vim.lsp.util.symbols_to_items(result, 0) @@ -282,7 +304,6 @@ local normalize_lsp_opts = function(opts, cfg) opts.bufnr = nil opts.winid = nil opts.filename = nil - opts.lsp_params = nil opts.code_actions = nil opts.num_results = nil opts.num_callbacks = nil @@ -323,6 +344,35 @@ M.implementations = function(opts) return fzf_lsp_locations(opts) end +-- see $VIMRUNTIME/lua/vim/buf.lua:pick_call_hierarchy_item() +M.call_hierarchy = function(opts) + opts.lsp_params = vim.lsp.util.make_position_params(0) + local method = "textDocument/prepareCallHierarchy" + local res, err = vim.lsp.buf_request_sync( + 0, method, opts.lsp_params, 2000) + if err then + utils.err(("Error executing '%s': %s"):format(method, err)) + else + local _, response = next(res) + if vim.tbl_isempty(response) then + utils.info(('No %s found'):format(opts.lsp_handler.label:lower())) + return + end + assert(response.result and response.result[1]) + local call_hierarchy_item = response.result[1] + opts.lsp_params = { item = call_hierarchy_item } + return fzf_lsp_locations(opts) + end +end + +M.incoming_calls = function(opts) + return M.call_hierarchy(opts) +end + +M.outgoing_calls = function(opts) + return M.call_hierarchy(opts) +end + M.document_symbols = function(opts) opts = set_async_default(opts, true) -- TODO: filename hiding @@ -730,10 +780,6 @@ M.live_workspace_symbols = function(opts) opts.search = nil end -M.incoming_calls = function(opts) - return fzf_lsp_locations(opts) -end - local function check_capabilities(feature) local clients = vim.lsp.buf_get_clients(0) @@ -814,8 +860,13 @@ local handlers = { ["incoming_calls"] = { label = "Incoming Calls", capability = "call_hierarchy", - method = "textDocument/prepareCallHierarchy", - handler = location_handler }, + method = "callHierarchy/incomingCalls", + handler = call_hierarchy_handler }, + ["outgoing_calls"] = { + label = "Outgoing Calls", + capability = "call_hierarchy", + method = "callHierarchy/outgoingCalls", + handler = call_hierarchy_handler }, } local function wrap_module_fncs(mod)