mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
fix(lsp): handle locations exceeding line length #30253
Problem: LSP spec [states](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position) that "if the character value is greater than the line length it defaults back to the line length", but `locations_to_items` fails in that case. Solution: Adjust locations_to_items to follow the spec. closes #28281
This commit is contained in:
parent
220b8aa6fe
commit
882a450a29
@ -1795,8 +1795,18 @@ function M.locations_to_items(locations, offset_encoding)
|
||||
local row = pos.line
|
||||
local end_row = end_pos.line
|
||||
local line = lines[row] or ''
|
||||
local col = M._str_byteindex_enc(line, pos.character, offset_encoding)
|
||||
local end_col = M._str_byteindex_enc(lines[end_row] or '', end_pos.character, offset_encoding)
|
||||
local line_len = vim.fn.strcharlen(line)
|
||||
local end_line = lines[end_row] or ''
|
||||
local end_line_len = vim.fn.strcharlen(end_line)
|
||||
-- LSP spec: if character > line length, default to the line length.
|
||||
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
|
||||
local col = pos.character <= line_len
|
||||
and M._str_byteindex_enc(line, pos.character, offset_encoding)
|
||||
or line_len
|
||||
local end_col = end_pos.character <= end_line_len
|
||||
and M._str_byteindex_enc(end_line, end_pos.character, offset_encoding)
|
||||
or end_line_len
|
||||
|
||||
table.insert(items, {
|
||||
filename = filename,
|
||||
lnum = row + 1,
|
||||
|
@ -2673,7 +2673,7 @@ describe('LSP', function()
|
||||
|
||||
describe('lsp.util.locations_to_items', function()
|
||||
it('Convert Location[] to items', function()
|
||||
local expected = {
|
||||
local expected_template = {
|
||||
{
|
||||
filename = '/fake/uri',
|
||||
lnum = 1,
|
||||
@ -2681,20 +2681,11 @@ describe('LSP', function()
|
||||
col = 3,
|
||||
end_col = 4,
|
||||
text = 'testing',
|
||||
user_data = {
|
||||
uri = 'file:///fake/uri',
|
||||
range = {
|
||||
start = { line = 0, character = 2 },
|
||||
['end'] = { line = 1, character = 3 },
|
||||
},
|
||||
},
|
||||
user_data = {},
|
||||
},
|
||||
}
|
||||
local actual = exec_lua(function()
|
||||
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
||||
local lines = { 'testing', '123' }
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
||||
local locations = {
|
||||
local test_params = {
|
||||
{
|
||||
{
|
||||
uri = 'file:///fake/uri',
|
||||
range = {
|
||||
@ -2702,10 +2693,29 @@ describe('LSP', function()
|
||||
['end'] = { line = 1, character = 3 },
|
||||
},
|
||||
},
|
||||
}
|
||||
return vim.lsp.util.locations_to_items(locations, 'utf-16')
|
||||
end)
|
||||
eq(expected, actual)
|
||||
},
|
||||
{
|
||||
{
|
||||
uri = 'file:///fake/uri',
|
||||
range = {
|
||||
start = { line = 0, character = 2 },
|
||||
-- LSP spec: if character > line length, default to the line length.
|
||||
['end'] = { line = 1, character = 10000 },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, params in ipairs(test_params) do
|
||||
local actual = exec_lua(function(params0)
|
||||
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
||||
local lines = { 'testing', '123' }
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
||||
return vim.lsp.util.locations_to_items(params0, 'utf-16')
|
||||
end, params)
|
||||
local expected = vim.deepcopy(expected_template)
|
||||
expected[1].user_data = params[1]
|
||||
eq(expected, actual)
|
||||
end
|
||||
end)
|
||||
|
||||
it('Convert LocationLink[] to items', function()
|
||||
|
Loading…
Reference in New Issue
Block a user