feat(lsp): pass arbitrary positions to vim.lsp.buf #39446

Problem:
Currently, it only supports sending requests using the current cursor position as a parameter.

Solution:
Support sending requests using arbitrary positions.
This commit is contained in:
Yi Ming
2026-05-11 01:49:36 +08:00
committed by GitHub
parent 1f4ad7808e
commit c2d7dd781a
3 changed files with 31 additions and 14 deletions

View File

@@ -1447,6 +1447,8 @@ the current buffer.
See |setqflist-what| for the structure of the `what`
parameter.
• {pos} (`vim.Pos`, default: cursor position) Position on a buffer
to request.
*vim.lsp.buf.hover.Opts*
Extends: |vim.lsp.util.open_floating_preview.Opts|

View File

@@ -156,8 +156,12 @@ LSP
"preselect". https://microsoft.github.io/language-server-protocol/specification/#completionClientCapabilities
• `textDocument/foldingRange` |vim.lsp.foldtext()| highlights collapsed text.
https://microsoft.github.io/language-server-protocol/specification/#textDocument_foldingRange
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|, |vim.lsp.buf.definition()|,
and |vim.lsp.buf.implementation()| now follows 'switchbuf'.
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|,
|vim.lsp.buf.type_definition()|, and |vim.lsp.buf.implementation()|
now follows 'switchbuf'.
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|,
|vim.lsp.buf.type_definition()|, and |vim.lsp.buf.implementation()|
now supports passing arbitrary positions.
• Support for nested snippets.
LUA
@@ -262,8 +266,9 @@ REMOVED FEATURES *news-removed*
These deprecated features were removed.
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|, |vim.lsp.buf.definition()|,
and |vim.lsp.buf.implementation()| no longer accept the `reuse_win` option.
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|,
|vim.lsp.buf.type_definition()|, and |vim.lsp.buf.implementation()|
no longer accept the `reuse_win` option.
==============================================================================
DEPRECATIONS *news-deprecations*

View File

@@ -225,23 +225,29 @@ local function get_locations(method, context, opts)
)
end
local bufnr = api.nvim_get_current_buf()
local win = api.nvim_get_current_win()
local pos = opts.pos or vim.pos.cursor(0, api.nvim_win_get_cursor(0))
local buf = pos.buf
local clients = lsp.get_clients({ method = method, bufnr = bufnr })
local clients = lsp.get_clients({ method = method, bufnr = buf })
if not next(clients) then
vim.notify(lsp._unsupported_method(method), vim.log.levels.WARN)
return
end
local from = vim.fn.getpos('.')
from[1] = bufnr
from[1] = buf
local tagname = vim.fn.expand('<cword>')
lsp.buf_request_all(bufnr, method, function(client)
local params = util.make_position_params(win, client.offset_encoding)
---@diagnostic disable-next-line: inject-field
params.context = context or { includeDeclaration = true }
lsp.buf_request_all(buf, method, function(client)
---@type lsp.TextDocumentPositionParams
local params = {
textDocument = util.make_text_document_params(buf),
position = pos:to_lsp(client.offset_encoding),
}
if method == 'textDocument/references' then
---@cast params lsp.ReferenceParams
params.context = context or { includeDeclaration = true }
end
return params
end, function(results)
---@type vim.quickfix.entry[]
@@ -267,7 +273,7 @@ local function get_locations(method, context, opts)
local what = {
title = name:gsub('^%l', string.upper),
items = all_items,
context = { bufnr = bufnr, method = method },
context = { bufnr = buf, method = method },
}
if opts.on_list then
validate('opts.on_list', opts.on_list, 'function')
@@ -285,7 +291,7 @@ local function get_locations(method, context, opts)
and method ~= 'textDocument/references'
then
local tagstack = { { tagname = tagname, from = from } }
vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't')
vim.fn.settagstack(vim.fn.bufwinid(buf), { items = tagstack }, 't')
if opts.loclist then
vim.cmd('lfirst')
else
@@ -338,6 +344,10 @@ end
--- vim.lsp.buf.references(nil, { loclist = false })
--- ```
--- @field loclist? boolean
---
--- Position on a buffer to request.
--- (default: cursor position)
--- @field pos vim.Pos
--- Jumps to the declaration of the symbol under the cursor.
--- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead.