Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lsp): pass server resp through client handlers (1) #2770

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 56 additions & 98 deletions lua/telescope/builtin/__lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,80 +9,6 @@ local utils = require "telescope.utils"

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)
vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
if err then
Expand Down Expand Up @@ -169,54 +95,77 @@ 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)
---@param err lsp.ResponseError
---@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, _)
if err then
vim.api.nvim_err_writeln("Error when executing " .. action .. " : " .. err.message)
return
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

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 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 #flattened_results == 0 then
if vim.tbl_isempty(items) then
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
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
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
local file_uri = flattened_results[1].uri
if file_uri == nil then
file_uri = flattened_results[1].targetUri
end
local file_path = vim.uri_to_fname(file_uri)
local file_path = vim.uri_to_fname(location_uri)
vim.cmd("tab drop " .. file_path)
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
local locations = vim.lsp.util.locations_to_items(flattened_results, offset_encoding)
pickers
.new(opts, {
prompt_title = title,
finder = finders.new_table {
results = locations,
results = items,
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
},
previewer = conf.qflist_previewer(opts),
Expand All @@ -229,16 +178,25 @@ local function list_or_jump(action, title, opts)
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)
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

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

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

local symbols_sorter = function(symbols)
Expand Down