Skip to content

Commit 6c468ff

Browse files
authored
feat(lsp): use native lsp handlers for some pickers (#3335)
Switch the following pickers to use the native neovim lsp handler functions using the `on_list` option: - `references` -> `vim.lsp.buf.references` - `definitions` -> `vim.lsp.buf.definition` - `type_definitions` -> `vim.lsp.buf.type_definition` - `implementations` -> `vim.lsp.buf.implementation` This offloads the request and response handling off the neovim. This also let's responses pass through any custom handlers registered via `vim.lsp.handlers`. This only affects users on neovim 0.11+. The `on_list` option was introduced in nvim 0.10 but only recently in 0.11, has neovim's `vim.lsp.buf.*` functions added improved support for responses from multiple language servers.
1 parent 37dc923 commit 6c468ff

File tree

1 file changed

+109
-4
lines changed

1 file changed

+109
-4
lines changed

lua/telescope/builtin/__lsp.lua

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,19 +261,107 @@ local function list_or_jump(action, title, funname, params, opts)
261261
end)
262262
end
263263

264-
lsp.references = function(opts)
264+
---@param item table
265+
---@param opts table
266+
local function jump(item, opts)
267+
if opts.curr_filepath ~= item.filename then
268+
local cmd
269+
if opts.jump_type == "tab" then
270+
cmd = "tabedit"
271+
elseif opts.jump_type == "split" then
272+
cmd = "new"
273+
elseif opts.jump_type == "vsplit" then
274+
cmd = "vnew"
275+
elseif opts.jump_type == "tab drop" then
276+
cmd = "tab drop"
277+
end
278+
279+
if cmd then
280+
vim.cmd(string.format("%s %s", cmd, item.filename))
281+
end
282+
end
283+
284+
local b = item.bufnr or vim.fn.bufadd(item.filename)
285+
vim.bo[b].buflisted = true
286+
local w = opts.reuse_win and vim.fn.win_findbuf(b)[1] or opts.winnr
287+
vim.api.nvim_win_set_buf(w, b)
288+
vim.api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 })
289+
vim._with({ win = w }, function()
290+
-- Open folds under the cursor
291+
vim.cmd "normal! zv"
292+
end)
293+
end
294+
295+
local function on_list_pick_or_jump(opts)
296+
opts.reuse_win = vim.F.if_nil(opts.reuse_win, false)
297+
opts.curr_filepath = vim.api.nvim_buf_get_name(opts.bufnr)
298+
299+
---@param res vim.lsp.LocationOpts.OnList
300+
return function(res)
301+
if opts.action_handler then
302+
res.items = opts.action_handler(res.items, opts)
303+
end
304+
305+
if #res.items == 1 and opts.jump_type ~= "never" then
306+
jump(res.items[1], opts)
307+
return
308+
end
309+
310+
pickers
311+
.new(opts, {
312+
finder = finders.new_table {
313+
results = res.items,
314+
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
315+
},
316+
previewer = conf.qflist_previewer(opts),
317+
sorter = conf.generic_sorter(opts),
318+
push_cursor_on_edit = true,
319+
push_tagstack_on_edit = true,
320+
})
321+
:find()
322+
end
323+
end
324+
325+
local function references(opts)
326+
opts.prompt_title = vim.F.if_nil(opts.prompt_title, "LSP References")
327+
328+
if not opts.include_current_line then
329+
opts.action_handler = function(items, ctx)
330+
local lnum = vim.api.nvim_win_get_cursor(ctx.winnr)[1]
331+
items = vim.tbl_filter(function(v)
332+
return not (v.filename == ctx.curr_filepath and v.lnum == lnum)
333+
end, items)
334+
return items
335+
end
336+
end
337+
338+
local ctx = { includeDeclaration = vim.F.if_nil(opts.include_declaration, true) }
339+
vim.lsp.buf.references(ctx, { on_list = on_list_pick_or_jump(opts) })
340+
end
341+
342+
local function references_legacy(opts)
265343
opts.include_current_line = vim.F.if_nil(opts.include_current_line, false)
266344
local params = vim.lsp.util.make_position_params(opts.winnr)
267345
params.context = { includeDeclaration = vim.F.if_nil(opts.include_declaration, true) }
268346
return list_or_jump("textDocument/references", "LSP References", "builtin.lsp_references", params, opts)
269347
end
270348

271-
lsp.definitions = function(opts)
349+
local function definitions(opts)
350+
opts.prompt_title = vim.F.if_nil(opts.prompt_title, "LSP Definitions")
351+
vim.lsp.buf.definition { on_list = on_list_pick_or_jump(opts) }
352+
end
353+
354+
local function definitions_legacy(opts)
272355
local params = vim.lsp.util.make_position_params(opts.winnr)
273356
return list_or_jump("textDocument/definition", "LSP Definitions", "builtin.lsp_definitions", params, opts)
274357
end
275358

276-
lsp.type_definitions = function(opts)
359+
local function type_definitions(opts)
360+
opts.prompt_title = vim.F.if_nil(opts.prompt_title, "LSP Type Definitions")
361+
vim.lsp.buf.type_definition { on_list = on_list_pick_or_jump(opts) }
362+
end
363+
364+
local function type_definitions_legacy(opts)
277365
local params = vim.lsp.util.make_position_params(opts.winnr)
278366
return list_or_jump(
279367
"textDocument/typeDefinition",
@@ -284,11 +372,28 @@ lsp.type_definitions = function(opts)
284372
)
285373
end
286374

287-
lsp.implementations = function(opts)
375+
local function implementations(opts)
376+
opts.prompt_title = vim.F.if_nil(opts.prompt_title, "LSP Implementations")
377+
vim.lsp.buf.implementation { on_list = on_list_pick_or_jump(opts) }
378+
end
379+
380+
local function implementations_legacy(opts)
288381
local params = vim.lsp.util.make_position_params(opts.winnr)
289382
return list_or_jump("textDocument/implementation", "LSP Implementations", "builtin.lsp_implementations", params, opts)
290383
end
291384

385+
if vim.fn.has "0.11" then
386+
lsp.references = references
387+
lsp.definitions = definitions
388+
lsp.type_definitions = type_definitions
389+
lsp.implementations = implementations
390+
else
391+
lsp.references = references_legacy
392+
lsp.definitions = definitions_legacy
393+
lsp.type_definitions = type_definitions_legacy
394+
lsp.implementations = implementations_legacy
395+
end
396+
292397
local symbols_sorter = function(symbols)
293398
if vim.tbl_isempty(symbols) then
294399
return symbols

0 commit comments

Comments
 (0)