mirror of
https://github.com/zoriya/telescope.nvim.git
synced 2025-12-06 06:46:10 +00:00
fix(lsp): pass server resp through client handlers (1)
For LSP methods/pickers: - references - definition - typeDefinition - implementation Passes the server results through client (and neovim's) lsp handler function. This lets those handlers deal with some of the language server specific idiosyncrasies. Also refactors shared code between these pickers. Other pickers/methods will need similar treatment.
This commit is contained in:
@@ -9,80 +9,6 @@ local utils = require "telescope.utils"
|
|||||||
|
|
||||||
local lsp = {}
|
local lsp = {}
|
||||||
|
|
||||||
lsp.references = function(opts)
|
|
||||||
local filepath = vim.api.nvim_buf_get_name(opts.bufnr)
|
|
||||||
local lnum = vim.api.nvim_win_get_cursor(opts.winnr)[1]
|
|
||||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
|
||||||
local include_current_line = vim.F.if_nil(opts.include_current_line, false)
|
|
||||||
params.context = { includeDeclaration = vim.F.if_nil(opts.include_declaration, true) }
|
|
||||||
|
|
||||||
vim.lsp.buf_request(opts.bufnr, "textDocument/references", params, function(err, result, ctx, _)
|
|
||||||
if err then
|
|
||||||
vim.api.nvim_err_writeln("Error when finding references: " .. err.message)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local locations = {}
|
|
||||||
if result then
|
|
||||||
local results = vim.lsp.util.locations_to_items(result, vim.lsp.get_client_by_id(ctx.client_id).offset_encoding)
|
|
||||||
if not include_current_line then
|
|
||||||
locations = vim.tbl_filter(function(v)
|
|
||||||
-- Remove current line from result
|
|
||||||
return not (v.filename == filepath and v.lnum == lnum)
|
|
||||||
end, vim.F.if_nil(results, {}))
|
|
||||||
else
|
|
||||||
locations = vim.F.if_nil(results, {})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if vim.tbl_isempty(locations) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #locations == 1 and opts.jump_type ~= "never" then
|
|
||||||
if filepath ~= locations[1].filename then
|
|
||||||
if opts.jump_type == "tab" then
|
|
||||||
vim.cmd "tabedit"
|
|
||||||
elseif opts.jump_type == "split" then
|
|
||||||
vim.cmd "new"
|
|
||||||
elseif opts.jump_type == "vsplit" then
|
|
||||||
vim.cmd "vnew"
|
|
||||||
elseif opts.jump_type == "tab drop" then
|
|
||||||
vim.cmd("tab drop " .. locations[1].filename)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- jump to location
|
|
||||||
local location = locations[1]
|
|
||||||
local bufnr = opts.bufnr
|
|
||||||
if location.filename then
|
|
||||||
local uri = location.filename
|
|
||||||
if not utils.is_uri(uri) then
|
|
||||||
uri = vim.uri_from_fname(uri)
|
|
||||||
end
|
|
||||||
|
|
||||||
bufnr = vim.uri_to_bufnr(uri)
|
|
||||||
end
|
|
||||||
vim.api.nvim_win_set_buf(0, bufnr)
|
|
||||||
vim.api.nvim_win_set_cursor(0, { location.lnum, location.col - 1 })
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
pickers
|
|
||||||
.new(opts, {
|
|
||||||
prompt_title = "LSP References",
|
|
||||||
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 call_hierarchy(opts, method, title, direction, item)
|
local function call_hierarchy(opts, method, title, direction, item)
|
||||||
vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
|
vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
|
||||||
if err then
|
if err then
|
||||||
@@ -169,30 +95,57 @@ lsp.outgoing_calls = function(opts)
|
|||||||
calls(opts, "to")
|
calls(opts, "to")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function list_or_jump(action, title, opts)
|
---@param err lsp.ResponseError
|
||||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
---@param result lsp.ProgressParams
|
||||||
|
---@param ctx lsp.HandlerContext
|
||||||
|
---@param action string
|
||||||
|
---@return table
|
||||||
|
local function pass_thru_client_handler(err, result, ctx, action)
|
||||||
|
local items
|
||||||
|
local function on_list(options)
|
||||||
|
items = options.items
|
||||||
|
end
|
||||||
|
|
||||||
|
if not vim.tbl_islist(result) then
|
||||||
|
result = { result }
|
||||||
|
end
|
||||||
|
|
||||||
|
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
||||||
|
local handler = client.handlers[action] or vim.lsp.handlers[action]
|
||||||
|
handler(err, result, ctx, { on_list = on_list })
|
||||||
|
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
|
local function list_or_jump(action, title, params, opts)
|
||||||
vim.lsp.buf_request(opts.bufnr, action, params, function(err, result, ctx, _)
|
vim.lsp.buf_request(opts.bufnr, action, params, function(err, result, ctx, _)
|
||||||
if err then
|
if err then
|
||||||
vim.api.nvim_err_writeln("Error when executing " .. action .. " : " .. err.message)
|
vim.api.nvim_err_writeln("Error when executing " .. action .. " : " .. err.message)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local flattened_results = {}
|
|
||||||
if result then
|
|
||||||
-- textDocument/definition can return Location or Location[]
|
|
||||||
if not vim.tbl_islist(result) then
|
|
||||||
flattened_results = { result }
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.list_extend(flattened_results, result)
|
if result == nil or vim.tbl_isempty(result) then
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local offset_encoding = vim.lsp.get_client_by_id(ctx.client_id).offset_encoding
|
local items = pass_thru_client_handler(err, result, ctx, action)
|
||||||
|
|
||||||
if #flattened_results == 0 then
|
if opts.include_current_line == false then
|
||||||
|
items = vim.tbl_filter(function(item)
|
||||||
|
return not (
|
||||||
|
item.filename == vim.api.nvim_buf_get_name(opts.bufnr)
|
||||||
|
and item.lnum == vim.api.nvim_win_get_cursor(opts.winnr)[1]
|
||||||
|
)
|
||||||
|
end, items)
|
||||||
|
end
|
||||||
|
|
||||||
|
if vim.tbl_isempty(items) then
|
||||||
return
|
return
|
||||||
elseif #flattened_results == 1 and opts.jump_type ~= "never" then
|
elseif #items == 1 and opts.jump_type ~= "never" then
|
||||||
|
local location = items[1].user_data
|
||||||
local uri = params.textDocument.uri
|
local uri = params.textDocument.uri
|
||||||
if uri ~= flattened_results[1].uri and uri ~= flattened_results[1].targetUri then
|
local location_uri = location.uri or location.targetUri
|
||||||
|
if uri ~= location_uri then
|
||||||
if opts.jump_type == "tab" then
|
if opts.jump_type == "tab" then
|
||||||
vim.cmd "tabedit"
|
vim.cmd "tabedit"
|
||||||
elseif opts.jump_type == "split" then
|
elseif opts.jump_type == "split" then
|
||||||
@@ -200,23 +153,19 @@ local function list_or_jump(action, title, opts)
|
|||||||
elseif opts.jump_type == "vsplit" then
|
elseif opts.jump_type == "vsplit" then
|
||||||
vim.cmd "vnew"
|
vim.cmd "vnew"
|
||||||
elseif opts.jump_type == "tab drop" then
|
elseif opts.jump_type == "tab drop" then
|
||||||
local file_uri = flattened_results[1].uri
|
local file_path = vim.uri_to_fname(location_uri)
|
||||||
if file_uri == nil then
|
|
||||||
file_uri = flattened_results[1].targetUri
|
|
||||||
end
|
|
||||||
local file_path = vim.uri_to_fname(file_uri)
|
|
||||||
vim.cmd("tab drop " .. file_path)
|
vim.cmd("tab drop " .. file_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.lsp.util.jump_to_location(flattened_results[1], offset_encoding, opts.reuse_win)
|
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
||||||
|
vim.lsp.util.jump_to_location(location, client.offset_encoding, opts.reuse_win)
|
||||||
else
|
else
|
||||||
local locations = vim.lsp.util.locations_to_items(flattened_results, offset_encoding)
|
|
||||||
pickers
|
pickers
|
||||||
.new(opts, {
|
.new(opts, {
|
||||||
prompt_title = title,
|
prompt_title = title,
|
||||||
finder = finders.new_table {
|
finder = finders.new_table {
|
||||||
results = locations,
|
results = items,
|
||||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||||
},
|
},
|
||||||
previewer = conf.qflist_previewer(opts),
|
previewer = conf.qflist_previewer(opts),
|
||||||
@@ -229,16 +178,25 @@ local function list_or_jump(action, title, opts)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
lsp.references = function(opts)
|
||||||
|
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||||
|
params.context = { includeDeclaration = vim.F.if_nil(opts.include_declaration, true) }
|
||||||
|
return list_or_jump("textDocument/references", "LSP References", params, opts)
|
||||||
|
end
|
||||||
|
|
||||||
lsp.definitions = function(opts)
|
lsp.definitions = function(opts)
|
||||||
return list_or_jump("textDocument/definition", "LSP Definitions", opts)
|
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||||
|
return list_or_jump("textDocument/definition", "LSP Definitions", params, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
lsp.type_definitions = function(opts)
|
lsp.type_definitions = function(opts)
|
||||||
return list_or_jump("textDocument/typeDefinition", "LSP Type Definitions", opts)
|
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||||
|
return list_or_jump("textDocument/typeDefinition", "LSP Type Definitions", params, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
lsp.implementations = function(opts)
|
lsp.implementations = function(opts)
|
||||||
return list_or_jump("textDocument/implementation", "LSP Implementations", opts)
|
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||||
|
return list_or_jump("textDocument/implementation", "LSP Implementations", params, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
local symbols_sorter = function(symbols)
|
local symbols_sorter = function(symbols)
|
||||||
|
|||||||
Reference in New Issue
Block a user