mirror of
https://github.com/neovim/neovim.git
synced 2026-07-19 15:41:32 +00:00
fix(lsp): support -1 column in format range #40570
Problem: `vim.lsp.buf.format()` accepts ranges using nvim indexing, where an end column of -1 means end of line. LSP ranges cannot use that, which is confusing for things like range formatting. Solution: Resolve -1 end columns to the line length before converting the range to LSP positions.
This commit is contained in:
@@ -1595,9 +1595,11 @@ format({opts}) *vim.lsp.buf.format()*
|
||||
default: current selection in visual mode, `nil` in other
|
||||
modes, formatting the full buffer) Range to format. Table
|
||||
must contain `start` and `end` keys with {row,col} tuples
|
||||
using (1,0) indexing. Can also be a list of tables that
|
||||
contain `start` and `end` keys as described above, in which
|
||||
case `textDocument/rangesFormatting` support is required.
|
||||
using (1,0) indexing. The end column can be -1 to format
|
||||
through the end of the line. Can also be a list of tables
|
||||
that contain `start` and `end` keys as described above, in
|
||||
which case `textDocument/rangesFormatting` support is
|
||||
required.
|
||||
• {timeout_ms}? (`integer`, default: `1000`) Time in
|
||||
milliseconds to block for formatting requests. No effect if
|
||||
async=true.
|
||||
|
||||
@@ -611,7 +611,7 @@ end
|
||||
---
|
||||
--- Range to format.
|
||||
--- Table must contain `start` and `end` keys with {row,col} tuples using
|
||||
--- (1,0) indexing.
|
||||
--- (1,0) indexing. The end column can be -1 to format through the end of the line.
|
||||
--- Can also be a list of tables that contain `start` and `end` keys as described above,
|
||||
--- in which case `textDocument/rangesFormatting` support is required.
|
||||
--- (Default: current selection in visual mode, `nil` in other modes,
|
||||
@@ -664,6 +664,13 @@ function M.format(opts)
|
||||
local function set_range(client, params)
|
||||
--- @param r {start:[integer,integer],end:[integer, integer]}
|
||||
local function to_lsp_range(r)
|
||||
if r['end'][2] == -1 then
|
||||
local end_line = api.nvim_buf_get_lines(bufnr, r['end'][1] - 1, r['end'][1], true)[1]
|
||||
return {
|
||||
start = vim.pos(bufnr, r.start[1] - 1, r.start[2]):to_lsp(client.offset_encoding),
|
||||
['end'] = vim.pos(bufnr, r['end'][1] - 1, #end_line):to_lsp(client.offset_encoding),
|
||||
}
|
||||
end
|
||||
return util.make_given_range_params(r.start, r['end'], bufnr, client.offset_encoding).range
|
||||
end
|
||||
|
||||
|
||||
@@ -1343,6 +1343,52 @@ describe('vim.lsp.buf', function()
|
||||
}
|
||||
end)
|
||||
|
||||
it('formats range ending with -1 column', function()
|
||||
exec_lua(create_server_definition)
|
||||
local result = exec_lua(function()
|
||||
local server = _G._create_server({
|
||||
capabilities = {
|
||||
documentRangeFormattingProvider = true,
|
||||
},
|
||||
handlers = {
|
||||
['textDocument/rangeFormatting'] = function(_, params, callback)
|
||||
callback(nil, {
|
||||
{
|
||||
range = params.range,
|
||||
newText = 'function fn(abc)\n print("hello")',
|
||||
},
|
||||
})
|
||||
end,
|
||||
},
|
||||
})
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
||||
vim.api.nvim_win_set_buf(0, bufnr)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, {
|
||||
'function fn(abc )',
|
||||
' print("hello" )',
|
||||
'end',
|
||||
})
|
||||
vim.lsp.buf.format({
|
||||
bufnr = bufnr,
|
||||
range = {
|
||||
start = { 1, 0 },
|
||||
['end'] = { 2, -1 },
|
||||
},
|
||||
})
|
||||
vim.lsp.get_client_by_id(client_id):stop()
|
||||
return {
|
||||
lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true),
|
||||
range = server.messages[3].params.range,
|
||||
}
|
||||
end)
|
||||
eq({
|
||||
start = { line = 0, character = 0 },
|
||||
['end'] = { line = 1, character = 17 },
|
||||
}, result.range)
|
||||
eq({ 'function fn(abc)', ' print("hello")', 'end' }, result.lines)
|
||||
end)
|
||||
|
||||
it('sends textDocument/rangesFormatting request to format multiple ranges', function()
|
||||
local expected_handlers = {
|
||||
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
||||
|
||||
Reference in New Issue
Block a user