mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
refactor(lsp): use vim.lsp.buf_request_all
internally (#34604)
This commit is contained in:

committed by
GitHub

parent
6942dec9b2
commit
40c61bf205
@@ -23,10 +23,6 @@ end
|
|||||||
---@return table[]
|
---@return table[]
|
||||||
local function query_definition(pattern)
|
local function query_definition(pattern)
|
||||||
local bufnr = api.nvim_get_current_buf()
|
local bufnr = api.nvim_get_current_buf()
|
||||||
local clients = vim.lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_definition })
|
|
||||||
if not next(clients) then
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
local win = api.nvim_get_current_win()
|
local win = api.nvim_get_current_win()
|
||||||
local results = {}
|
local results = {}
|
||||||
|
|
||||||
@@ -37,33 +33,35 @@ local function query_definition(pattern)
|
|||||||
table.insert(results, mk_tag_item(pattern, range, uri, position_encoding))
|
table.insert(results, mk_tag_item(pattern, range, uri, position_encoding))
|
||||||
end
|
end
|
||||||
|
|
||||||
local remaining = #clients
|
local request_results, _ = lsp.buf_request_sync(
|
||||||
for _, client in ipairs(clients) do
|
bufnr,
|
||||||
---@param result nil|lsp.Location|lsp.Location[]|lsp.LocationLink[]
|
ms.textDocument_definition,
|
||||||
local function on_response(_, result)
|
function(client)
|
||||||
if result then
|
return util.make_position_params(win, client.offset_encoding)
|
||||||
local encoding = client.offset_encoding
|
end
|
||||||
-- single Location
|
)
|
||||||
if result.range then
|
|
||||||
add(result.range, result.uri, encoding)
|
for client_id, res in pairs(request_results or {}) do
|
||||||
else
|
local client = assert(lsp.get_client_by_id(client_id))
|
||||||
for _, location in ipairs(result) do
|
local result = res.result ---@type lsp.Location|lsp.Location[]|lsp.LocationLink[]|nil
|
||||||
if location.range then -- Location
|
|
||||||
add(location.range, location.uri, encoding)
|
if result then
|
||||||
else -- LocationLink
|
local encoding = client.offset_encoding
|
||||||
add(location.targetSelectionRange, location.targetUri, encoding)
|
-- single Location
|
||||||
end
|
if result.range then
|
||||||
|
add(result.range, result.uri, encoding)
|
||||||
|
else
|
||||||
|
for _, location in ipairs(result) do
|
||||||
|
if location.range then -- Location
|
||||||
|
add(location.range, location.uri, encoding)
|
||||||
|
else -- LocationLink
|
||||||
|
add(location.targetSelectionRange, location.targetUri, encoding)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
remaining = remaining - 1
|
|
||||||
end
|
end
|
||||||
local params = util.make_position_params(win, client.offset_encoding)
|
|
||||||
client:request(ms.textDocument_definition, params, on_response, bufnr)
|
|
||||||
end
|
end
|
||||||
vim.wait(1000, function()
|
|
||||||
return remaining == 0
|
|
||||||
end)
|
|
||||||
return results
|
return results
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -165,88 +165,84 @@ end
|
|||||||
local function get_locations(method, opts)
|
local function get_locations(method, opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
local bufnr = api.nvim_get_current_buf()
|
local bufnr = api.nvim_get_current_buf()
|
||||||
|
local win = api.nvim_get_current_win()
|
||||||
|
|
||||||
local clients = lsp.get_clients({ method = method, bufnr = bufnr })
|
local clients = lsp.get_clients({ method = method, bufnr = bufnr })
|
||||||
if not next(clients) then
|
if not next(clients) then
|
||||||
vim.notify(lsp._unsupported_method(method), vim.log.levels.WARN)
|
vim.notify(lsp._unsupported_method(method), vim.log.levels.WARN)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local win = api.nvim_get_current_win()
|
|
||||||
local from = vim.fn.getpos('.')
|
local from = vim.fn.getpos('.')
|
||||||
from[1] = bufnr
|
from[1] = bufnr
|
||||||
local tagname = vim.fn.expand('<cword>')
|
local tagname = vim.fn.expand('<cword>')
|
||||||
local remaining = #clients
|
|
||||||
|
|
||||||
---@type vim.quickfix.entry[]
|
lsp.buf_request_all(bufnr, method, function(client)
|
||||||
local all_items = {}
|
return util.make_position_params(win, client.offset_encoding)
|
||||||
|
end, function(results)
|
||||||
|
---@type vim.quickfix.entry[]
|
||||||
|
local all_items = {}
|
||||||
|
|
||||||
---@param result nil|lsp.Location|lsp.Location[]
|
for client_id, res in pairs(results) do
|
||||||
---@param client vim.lsp.Client
|
local client = assert(lsp.get_client_by_id(client_id))
|
||||||
local function on_response(_, result, client)
|
local locations = {}
|
||||||
local locations = {}
|
if res then
|
||||||
if result then
|
locations = vim.islist(res.result) and res.result or { res.result }
|
||||||
locations = vim.islist(result) and result or { result }
|
end
|
||||||
|
local items = util.locations_to_items(locations, client.offset_encoding)
|
||||||
|
vim.list_extend(all_items, items)
|
||||||
end
|
end
|
||||||
local items = util.locations_to_items(locations, client.offset_encoding)
|
|
||||||
vim.list_extend(all_items, items)
|
|
||||||
remaining = remaining - 1
|
|
||||||
if remaining == 0 then
|
|
||||||
if vim.tbl_isempty(all_items) then
|
|
||||||
vim.notify('No locations found', vim.log.levels.INFO)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local title = 'LSP locations'
|
if vim.tbl_isempty(all_items) then
|
||||||
if opts.on_list then
|
vim.notify('No locations found', vim.log.levels.INFO)
|
||||||
assert(vim.is_callable(opts.on_list), 'on_list is not a function')
|
return
|
||||||
opts.on_list({
|
end
|
||||||
title = title,
|
|
||||||
items = all_items,
|
|
||||||
context = { bufnr = bufnr, method = method },
|
|
||||||
})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #all_items == 1 then
|
local title = 'LSP locations'
|
||||||
local item = all_items[1]
|
if opts.on_list then
|
||||||
local b = item.bufnr or vim.fn.bufadd(item.filename)
|
assert(vim.is_callable(opts.on_list), 'on_list is not a function')
|
||||||
|
opts.on_list({
|
||||||
|
title = title,
|
||||||
|
items = all_items,
|
||||||
|
context = { bufnr = bufnr, method = method },
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Save position in jumplist
|
if #all_items == 1 then
|
||||||
vim.cmd("normal! m'")
|
local item = all_items[1]
|
||||||
-- Push a new item into tagstack
|
local b = item.bufnr or vim.fn.bufadd(item.filename)
|
||||||
local tagstack = { { tagname = tagname, from = from } }
|
|
||||||
vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't')
|
|
||||||
|
|
||||||
vim.bo[b].buflisted = true
|
-- Save position in jumplist
|
||||||
local w = win
|
vim.cmd("normal! m'")
|
||||||
if opts.reuse_win then
|
-- Push a new item into tagstack
|
||||||
w = vim.fn.win_findbuf(b)[1] or w
|
local tagstack = { { tagname = tagname, from = from } }
|
||||||
if w ~= win then
|
vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't')
|
||||||
api.nvim_set_current_win(w)
|
|
||||||
end
|
vim.bo[b].buflisted = true
|
||||||
|
local w = win
|
||||||
|
if opts.reuse_win then
|
||||||
|
w = vim.fn.win_findbuf(b)[1] or w
|
||||||
|
if w ~= win then
|
||||||
|
api.nvim_set_current_win(w)
|
||||||
end
|
end
|
||||||
api.nvim_win_set_buf(w, b)
|
|
||||||
api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 })
|
|
||||||
vim._with({ win = w }, function()
|
|
||||||
-- Open folds under the cursor
|
|
||||||
vim.cmd('normal! zv')
|
|
||||||
end)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if opts.loclist then
|
|
||||||
vim.fn.setloclist(0, {}, ' ', { title = title, items = all_items })
|
|
||||||
vim.cmd.lopen()
|
|
||||||
else
|
|
||||||
vim.fn.setqflist({}, ' ', { title = title, items = all_items })
|
|
||||||
vim.cmd('botright copen')
|
|
||||||
end
|
end
|
||||||
|
api.nvim_win_set_buf(w, b)
|
||||||
|
api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 })
|
||||||
|
vim._with({ win = w }, function()
|
||||||
|
-- Open folds under the cursor
|
||||||
|
vim.cmd('normal! zv')
|
||||||
|
end)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
if opts.loclist then
|
||||||
for _, client in ipairs(clients) do
|
vim.fn.setloclist(0, {}, ' ', { title = title, items = all_items })
|
||||||
local params = util.make_position_params(win, client.offset_encoding)
|
vim.cmd.lopen()
|
||||||
client:request(method, params, function(_, result)
|
else
|
||||||
on_response(_, result, client)
|
vim.fn.setqflist({}, ' ', { title = title, items = all_items })
|
||||||
end)
|
vim.cmd('botright copen')
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @class vim.lsp.ListOpts
|
--- @class vim.lsp.ListOpts
|
||||||
@@ -795,17 +791,24 @@ function M.references(context, opts)
|
|||||||
validate('opts', opts, 'table', true)
|
validate('opts', opts, 'table', true)
|
||||||
|
|
||||||
local bufnr = api.nvim_get_current_buf()
|
local bufnr = api.nvim_get_current_buf()
|
||||||
local clients = lsp.get_clients({ method = ms.textDocument_references, bufnr = bufnr })
|
|
||||||
if not next(clients) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local win = api.nvim_get_current_win()
|
local win = api.nvim_get_current_win()
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
|
|
||||||
local all_items = {}
|
lsp.buf_request_all(bufnr, ms.textDocument_references, function(client)
|
||||||
local title = 'References'
|
local params = util.make_position_params(win, client.offset_encoding)
|
||||||
|
---@diagnostic disable-next-line: inject-field
|
||||||
|
params.context = context or { includeDeclaration = true }
|
||||||
|
return params
|
||||||
|
end, function(results)
|
||||||
|
local all_items = {}
|
||||||
|
local title = 'References'
|
||||||
|
|
||||||
|
for client_id, res in pairs(results) do
|
||||||
|
local client = assert(lsp.get_client_by_id(client_id))
|
||||||
|
local items = util.locations_to_items(res.result, client.offset_encoding)
|
||||||
|
vim.list_extend(all_items, items)
|
||||||
|
end
|
||||||
|
|
||||||
local function on_done()
|
|
||||||
if not next(all_items) then
|
if not next(all_items) then
|
||||||
vim.notify('No references found')
|
vim.notify('No references found')
|
||||||
else
|
else
|
||||||
@@ -828,25 +831,7 @@ function M.references(context, opts)
|
|||||||
vim.cmd('botright copen')
|
vim.cmd('botright copen')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
local remaining = #clients
|
|
||||||
for _, client in ipairs(clients) do
|
|
||||||
local params = util.make_position_params(win, client.offset_encoding)
|
|
||||||
|
|
||||||
---@diagnostic disable-next-line: inject-field
|
|
||||||
params.context = context or {
|
|
||||||
includeDeclaration = true,
|
|
||||||
}
|
|
||||||
client:request(ms.textDocument_references, params, function(_, result)
|
|
||||||
local items = util.locations_to_items(result or {}, client.offset_encoding)
|
|
||||||
vim.list_extend(all_items, items)
|
|
||||||
remaining = remaining - 1
|
|
||||||
if remaining == 0 then
|
|
||||||
on_done()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Lists all symbols in the current buffer in the |location-list|.
|
--- Lists all symbols in the current buffer in the |location-list|.
|
||||||
@@ -909,8 +894,21 @@ local function hierarchy(method)
|
|||||||
|
|
||||||
local win = api.nvim_get_current_win()
|
local win = api.nvim_get_current_win()
|
||||||
|
|
||||||
--- @param results [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][]
|
lsp.buf_request_all(bufnr, prepare_method, function(client)
|
||||||
local function on_response(results)
|
return util.make_position_params(win, client.offset_encoding)
|
||||||
|
end, function(req_results)
|
||||||
|
local results = {} --- @type [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][]
|
||||||
|
for client_id, res in pairs(req_results) do
|
||||||
|
if res.err then
|
||||||
|
vim.notify(res.err.message, vim.log.levels.WARN)
|
||||||
|
elseif res.result then
|
||||||
|
local result = res.result --- @type lsp.TypeHierarchyItem[]|lsp.CallHierarchyItem[]
|
||||||
|
for _, item in ipairs(result) do
|
||||||
|
results[#results + 1] = { client_id, item }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if #results == 0 then
|
if #results == 0 then
|
||||||
vim.notify('No item resolved', vim.log.levels.WARN)
|
vim.notify('No item resolved', vim.log.levels.WARN)
|
||||||
elseif #results == 1 then
|
elseif #results == 1 then
|
||||||
@@ -930,30 +928,7 @@ local function hierarchy(method)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
local results = {} --- @type [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][]
|
|
||||||
|
|
||||||
local remaining = #clients
|
|
||||||
|
|
||||||
for _, client in ipairs(clients) do
|
|
||||||
local params = util.make_position_params(win, client.offset_encoding)
|
|
||||||
--- @param result lsp.CallHierarchyItem[]|lsp.TypeHierarchyItem[]?
|
|
||||||
client:request(prepare_method, params, function(err, result, ctx)
|
|
||||||
if err then
|
|
||||||
vim.notify(err.message, vim.log.levels.WARN)
|
|
||||||
elseif result then
|
|
||||||
for _, item in ipairs(result) do
|
|
||||||
results[#results + 1] = { ctx.client_id, item }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
remaining = remaining - 1
|
|
||||||
if remaining == 0 then
|
|
||||||
on_response(results)
|
|
||||||
end
|
|
||||||
end, bufnr)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Lists all the call sites of the symbol under the cursor in the
|
--- Lists all the call sites of the symbol under the cursor in the
|
||||||
@@ -1098,7 +1073,7 @@ end
|
|||||||
|
|
||||||
---@nodoc
|
---@nodoc
|
||||||
---@class vim.lsp.CodeActionResultEntry
|
---@class vim.lsp.CodeActionResultEntry
|
||||||
---@field error? lsp.ResponseError
|
---@field err? lsp.ResponseError
|
||||||
---@field result? (lsp.Command|lsp.CodeAction)[]
|
---@field result? (lsp.Command|lsp.CodeAction)[]
|
||||||
---@field ctx lsp.HandlerContext
|
---@field ctx lsp.HandlerContext
|
||||||
|
|
||||||
@@ -1306,29 +1281,14 @@ function M.code_action(opts)
|
|||||||
local bufnr = api.nvim_get_current_buf()
|
local bufnr = api.nvim_get_current_buf()
|
||||||
local win = api.nvim_get_current_win()
|
local win = api.nvim_get_current_win()
|
||||||
local clients = lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_codeAction })
|
local clients = lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_codeAction })
|
||||||
local remaining = #clients
|
if not next(clients) then
|
||||||
if remaining == 0 then
|
|
||||||
if next(lsp.get_clients({ bufnr = bufnr })) then
|
if next(lsp.get_clients({ bufnr = bufnr })) then
|
||||||
vim.notify(lsp._unsupported_method(ms.textDocument_codeAction), vim.log.levels.WARN)
|
vim.notify(lsp._unsupported_method(ms.textDocument_codeAction), vim.log.levels.WARN)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type table<integer, vim.lsp.CodeActionResultEntry>
|
lsp.buf_request_all(bufnr, ms.textDocument_codeAction, function(client)
|
||||||
local results = {}
|
|
||||||
|
|
||||||
---@param err? lsp.ResponseError
|
|
||||||
---@param result? (lsp.Command|lsp.CodeAction)[]
|
|
||||||
---@param ctx lsp.HandlerContext
|
|
||||||
local function on_result(err, result, ctx)
|
|
||||||
results[ctx.client_id] = { error = err, result = result, ctx = ctx }
|
|
||||||
remaining = remaining - 1
|
|
||||||
if remaining == 0 then
|
|
||||||
on_code_action_results(results, opts)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, client in ipairs(clients) do
|
|
||||||
---@type lsp.CodeActionParams
|
---@type lsp.CodeActionParams
|
||||||
local params
|
local params
|
||||||
|
|
||||||
@@ -1364,8 +1324,15 @@ function M.code_action(opts)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
client:request(ms.textDocument_codeAction, params, on_result, bufnr)
|
return params
|
||||||
end
|
end, function(results, ctx)
|
||||||
|
for _, result in pairs(results) do
|
||||||
|
---@cast result vim.lsp.CodeActionResultEntry
|
||||||
|
result.ctx = ctx
|
||||||
|
end
|
||||||
|
|
||||||
|
on_code_action_results(results, opts)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @deprecated
|
--- @deprecated
|
||||||
|
@@ -430,6 +430,8 @@ function M._convert_results(
|
|||||||
return matches, server_start_boundary
|
return matches, server_start_boundary
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- NOTE: The reason we don't use `lsp.buf_request_all` here is because we want to filter the clients
|
||||||
|
-- that received the request based on the trigger characters.
|
||||||
--- @param clients table<integer, vim.lsp.Client> # keys != client_id
|
--- @param clients table<integer, vim.lsp.Client> # keys != client_id
|
||||||
--- @param bufnr integer
|
--- @param bufnr integer
|
||||||
--- @param win integer
|
--- @param win integer
|
||||||
|
Reference in New Issue
Block a user