@ -1,7 +1,7 @@
local gui = require ( ' navigator.gui ' )
local gui = require ( ' navigator.gui ' )
local util = require ( ' navigator.util ' )
local util = require ( ' navigator.util ' )
local log = util.log
local log = util.log
local trace = util. trace
local trace = util. log
local partial = util.partial
local partial = util.partial
local lsphelper = require ( ' navigator.lspwrapper ' )
local lsphelper = require ( ' navigator.lspwrapper ' )
@ -9,94 +9,162 @@ local path_sep = require('navigator.util').path_sep()
local path_cur = require ( ' navigator.util ' ) . path_cur ( )
local path_cur = require ( ' navigator.util ' ) . path_cur ( )
local cwd = vim.loop . cwd ( )
local cwd = vim.loop . cwd ( )
local M = { }
local M = { }
local function call_hierarchy_handler ( direction , err , result , ctx , _ , error_message )
local outgoing_calls_handler
local incoming_calls_handler
local function call_hierarchy_handler ( direction , err , result , ctx , config )
log ( direction , err , result , ctx , config )
if not result then
if not result then
vim.notify ( ' No call hierarchy items found ' , vim.lsp . log_levels.WARN )
vim.notify ( ' No call hierarchy items found ' , vim.lsp . log_levels.WARN )
return
return
end
end
trace ( ' call_hierarchy ' , result )
-- trace('call_hierarchy', result )
local bufnr = vim.api . nvim_get_current_buf ( )
local bufnr = vim.api . nvim_get_current_buf ( )
assert ( next ( vim.lsp . buf_get_clients ( bufnr ) ) , ' Must have a client running to use lsp_tags ' )
assert ( next ( vim.lsp . buf_get_clients ( bufnr ) ) , ' Must have a client running to use lsp_tags ' )
if err ~= nil then
if err ~= nil then
log ( ' dir ' , direction , ' result ' , result , ' err ' , err , ctx )
log ( ' dir ' , direction , ' result ' , result , ' err ' , err , ctx )
vim.notify ( ' ERROR: ' .. err or_message , vim.lsp . log_levels.WARN )
vim.notify ( ' ERROR: ' .. err , vim.lsp . log_levels.WARN )
return
return
end
end
local items = { }
local items = ctx.items or { }
for _ , call_hierarchy_ call in pairs ( result ) do
for _ , call_hierarchy_ result in pairs ( result ) do
local call_hierarchy_item = call_hierarchy_ call [ direction ]
local call_hierarchy_item = call_hierarchy_ result [ direction ]
local kind = ' '
local kind = ' '
if call_hierarchy_item.kind then
if call_hierarchy_item.kind then
kind = require ( ' navigator.lspclient.lspkind ' ) . symbol_kind ( call_hierarchy_item.kind ) .. ' '
kind = require ( ' navigator.lspclient.lspkind ' ) . symbol_kind ( call_hierarchy_item.kind ) .. ' '
end
end
-- for _, range in pairs(call_hierarchy_call.fromRanges) do
local range = call_hierarchy_item.range or call_hierarchy_item.selectionRange
local filename = assert ( vim.uri_to_fname ( call_hierarchy_item.uri ) )
local filename = assert ( vim.uri_to_fname ( call_hierarchy_item.uri ) )
local display_filename = filename : gsub ( cwd .. path_sep , path_cur , 1 )
local display_filename = filename : gsub ( cwd .. path_sep , path_cur , 1 )
call_hierarchy_item.detail = call_hierarchy_item.detail or ' '
call_hierarchy_item.detail = call_hierarchy_item.detail or ' '
call_hierarchy_item.detail = string.gsub ( call_hierarchy_item.detail , ' \n ' , ' ↳ ' )
call_hierarchy_item.detail = string.gsub ( call_hierarchy_item.detail , ' \n ' , ' ↳ ' )
trace ( r ang e, call_hierarchy_item )
trace ( r esult , call_hierarchy_item )
local disp_item = {
local disp_item = vim.tbl_deep_extend ( ' force ' , { } , call_hierarchy_item )
uri = call_hierarchy_item.uri ,
disp_item = vim.tbl_deep_extend ( ' force ' , disp_item , {
filename = filename ,
filename = filename ,
display_filename = display_filename ,
display_filename = display_filename ,
indent = ctx.depth ,
text = kind .. call_hierarchy_item.name .. ' ﰲ ' .. call_hierarchy_item.detail ,
text = kind .. call_hierarchy_item.name .. ' ﰲ ' .. call_hierarchy_item.detail ,
range = range ,
lnum = call_hierarchy_item.selectionRange . start.line + 1 ,
lnum = range.start . line + 1 ,
col = call_hierarchy_item.selectionRange . start.character ,
col = range.start . character ,
} )
}
table.insert ( items , disp_item )
table.insert ( items , disp_item )
-- end
if ctx.depth or 0 > 0 then
local params = {
position = {
character = disp_item.selectionRange . start.character ,
line = disp_item.selectionRange . start.line ,
} ,
textDocument = {
uri = disp_item.uri ,
} ,
}
local api = ' callHierarchy/outgoingCalls '
local handler = outgoing_calls_handler
if direction == ' incoming ' then
api = ' callHierarchy/incomingCalls '
handler = incoming_calls_handler
end
lsphelper.call_sync (
api ,
params ,
ctx ,
vim.lsp . with (
partial ( handler , 0 ) ,
{ depth = ctx.depth - 1 , direction = ' to ' , items = ctx.items , no_show = true }
)
)
end
end
end
log ( items )
return items
return items
end
end
local call_hierarchy_handler_from = partial ( call_hierarchy_handler , ' from ' )
local call_hierarchy_handler_from = partial ( call_hierarchy_handler , ' from ' )
local call_hierarchy_handler_to = partial ( call_hierarchy_handler , ' to ' )
local call_hierarchy_handler_to = partial ( call_hierarchy_handler , ' to ' )
-- local function incoming_calls_handler(bang, err, result, ctx, cfg)
incoming_calls_handler = function ( _ , err , result , ctx , cfg )
local function incoming_calls_handler ( _ , err , result , ctx , cfg )
local bufnr = vim.api . nvim_get_current_buf ( )
local bufnr = vim.api . nvim_get_current_buf ( )
assert ( next ( vim.lsp . buf_get_clients ( bufnr ) ) , ' Must have a client running to use lsp hierarchy ' )
assert ( next ( vim.lsp . buf_get_clients ( bufnr ) ) , ' Must have a client running to use lsp hierarchy ' )
local results = call_hierarchy_handler_from ( err , result , ctx , cfg , ' Incoming calls not found ' )
local results = call_hierarchy_handler_from ( err , result , ctx , cfg , ' Incoming calls not found ' )
local ft = vim.api . nvim_buf_get_option ( ctx.bufnr , ' ft ' )
local ft = vim.api . nvim_buf_get_option ( ctx.bufnr or vim.api . nvim_get_current_buf ( ) , ' ft ' )
gui.new_list_view ( { items = results , ft = ft , api = ' ' } )
if ctx.no_show then
return results
end
local win = gui.new_list_view ( { items = results , ft = ft , api = ' ' } )
return results , win
end
end
local function outgoing_calls_handler ( _ , err , result , ctx , cfg )
outgoing_calls_handler = function ( _ , err , result , ctx , cfg )
local results = call_hierarchy_handler_to ( err , result , ctx , cfg , ' Outgoing calls not found ' )
local results = call_hierarchy_handler_to ( err , result , ctx , cfg , ' Outgoing calls not found ' )
local ft = vim.api . nvim_buf_get_option ( ctx.bufnr , ' ft ' )
local ft = vim.api . nvim_buf_get_option ( ctx.bufnr , ' ft ' )
gui.new_list_view ( { items = results , ft = ft , api = ' ' } )
if ctx.no_show then
-- fzf_locations(bang, "", "Outgoing Calls", results, false)
return results
end
local win = gui.new_list_view ( { items = results , ft = ft , api = ' ' } )
return result , win
end
end
function M . incoming_calls ( bang , opts )
local function request ( method , params , handler )
local bufnr = vim.api . nvim_get_current_buf ( )
return vim.lsp . buf_request ( 0 , method , params , handler )
assert ( next ( vim.lsp . buf_get_clients ( bufnr ) ) , ' Must have a client running to use lsp hierarchy ' )
end
if not lsphelper.check_capabilities ( ' callHierarchyProvider ' ) then
local function pick_call_hierarchy_item ( call_hierarchy_items )
if not call_hierarchy_items then
return
return
end
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 call_hierarchy ( method , opts )
local params = vim.lsp . util.make_position_params ( )
local params = vim.lsp . util.make_position_params ( )
lsphelper.call_sync ( ' callHierarchy/incomingCalls ' , params , opts , partial ( incoming_calls_handler , bang ) )
opts = opts or { }
request (
' textDocument/prepareCallHierarchy ' ,
params ,
vim.lsp . with ( function ( err , result , ctx )
if err then
vim.notify ( err.message , vim.log . levels.WARN )
return
end
local call_hierarchy_item = pick_call_hierarchy_item ( result )
log ( ' result ' , result , ' items ' , call_hierarchy_item )
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
end , { direction = method , depth = opts.depth } )
)
end
end
function M . outgoing_calls ( bang , opts )
function M . incoming_calls ( opts )
local bufnr = vim.api . nvim_get_current_buf ( )
call_hierarchy ( ' callHierarchy/incomingCalls ' , opts )
assert ( next ( vim.lsp . buf_get_clients ( bufnr ) ) , ' Must have a client running to use lsp_tags ' )
end
if not lsphelper.check_capabilities ( ' callHierarchyProvider ' ) then
return
end
local params = vim.lsp . util.make_position_params ( )
function M . outgoing_calls ( opts )
lsphelper.call_sync ( ' callHierarchy/outgoingCalls ' , params , opts , partial ( outgoing_calls_handler , bang ) )
call_hierarchy ( ' callHierarchy/outgoingCalls ' , opts )
end
end
M.incoming_calls_call = partial ( M.incoming_calls , 0 )
M.incoming_calls_call = partial ( M.incoming_calls , 0 )