From 99b6c399260cd0e03511032f62867cff1906782d Mon Sep 17 00:00:00 2001 From: Yi Ming Date: Wed, 11 Dec 2024 12:05:54 +0800 Subject: [PATCH] feat(lsp)!: `location_to_items` and `symbol_to_item` require `offset_encoding` --- runtime/doc/lsp.txt | 8 +++++--- runtime/doc/news.txt | 2 ++ runtime/lua/vim/lsp/handlers.lua | 5 +++-- runtime/lua/vim/lsp/util.lua | 18 ++++++++++++++---- test/functional/plugin/lsp_spec.lua | 14 ++++++++++++++ 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 64145ebf11..844372eeda 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -2380,12 +2380,14 @@ stylize_markdown({bufnr}, {contents}, {opts}) Return: ~ (`table`) stripped content -symbols_to_items({symbols}, {bufnr}) *vim.lsp.util.symbols_to_items()* + *vim.lsp.util.symbols_to_items()* +symbols_to_items({symbols}, {bufnr}, {position_encoding}) Converts symbols to quickfix list items. Parameters: ~ - • {symbols} (`lsp.DocumentSymbol[]|lsp.SymbolInformation[]`) - • {bufnr} (`integer?`) + • {symbols} (`lsp.DocumentSymbol[]|lsp.SymbolInformation[]`) + • {bufnr} (`integer?`) + • {position_encoding} (`'utf-8'|'utf-16'|'utf-32'`) Return: ~ (`vim.quickfix.entry[]`) See |setqflist()| for the format diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index eb6e6fb773..f83b0ab495 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -110,6 +110,8 @@ LSP • |vim.lsp.util.make_position_params()|, |vim.lsp.util.make_range_params()| and |vim.lsp.util.make_given_range_params()| now require the `position_encoding` parameter. +• |vim.lsp.util.location_to_items| and |vim.lsp.util.symbols_to_items()| now + requires the `position_encoding` parameter. LUA diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 1945040bda..3fb52ae0f5 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -231,7 +231,7 @@ end --- --- The returned function has an optional {config} parameter that accepts |vim.lsp.ListOpts| --- ----@param map_result fun(resp, bufnr: integer): table to convert the response +---@param map_result fun(resp, bufnr: integer, position_encoding: 'utf-8'|'utf-16'|'utf-32'): table to convert the response ---@param entity string name of the resource used in a `not found` error message ---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title ---@return lsp.Handler @@ -244,7 +244,8 @@ local function response_to_list(map_result, entity, title_fn) end config = config or {} local title = title_fn(ctx) - local items = map_result(result, ctx.bufnr) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + local items = map_result(result, ctx.bufnr, client.offset_encoding) local list = { title = title, items = items, context = ctx } if config.loclist then diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 050c0e42ec..2c66075ff7 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1774,9 +1774,19 @@ end --- ---@param symbols lsp.DocumentSymbol[]|lsp.SymbolInformation[] ---@param bufnr? integer +---@param position_encoding 'utf-8'|'utf-16'|'utf-32' ---@return vim.quickfix.entry[] # See |setqflist()| for the format -function M.symbols_to_items(symbols, bufnr) +function M.symbols_to_items(symbols, bufnr, position_encoding) bufnr = bufnr or 0 + if position_encoding == nil then + vim.notify_once( + 'symbols_to_items must be called with valid position encoding', + vim.log.levels.WARN + ) + local clients = vim.lsp.get_clients({ bufnr = bufnr }) + position_encoding = vim.tbl_isempty(clients) and 'utf-16' or clients[1].offset_encoding + end + local items = {} --- @type vim.quickfix.entry[] for _, symbol in ipairs(symbols) do --- @type string?, lsp.Range? @@ -1796,9 +1806,9 @@ function M.symbols_to_items(symbols, bufnr) local kind = protocol.SymbolKind[symbol.kind] or 'Unknown' local lnum = range['start'].line + 1 - local col = range['start'].character + 1 + local col = get_line_byte_from_position(bufnr, range['start'], position_encoding) + 1 local end_lnum = range['end'].line + 1 - local end_col = range['end'].character + 1 + local end_col = get_line_byte_from_position(bufnr, range['end'], position_encoding) + 1 items[#items + 1] = { filename = filename, @@ -1812,7 +1822,7 @@ function M.symbols_to_items(symbols, bufnr) end if symbol.children then - list_extend(items, M.symbols_to_items(symbol.children, bufnr)) + list_extend(items, M.symbols_to_items(symbol.children, bufnr, position_encoding)) end end diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 79952cb933..0bf3f7ac85 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -2916,6 +2916,8 @@ describe('LSP', function() local expected = { { col = 1, + end_col = 1, + end_lnum = 2, filename = '', kind = 'File', lnum = 2, @@ -2923,6 +2925,8 @@ describe('LSP', function() }, { col = 1, + end_col = 1, + end_lnum = 4, filename = '', kind = 'Module', lnum = 4, @@ -2930,6 +2934,8 @@ describe('LSP', function() }, { col = 1, + end_col = 1, + end_lnum = 6, filename = '', kind = 'Namespace', lnum = 6, @@ -3031,6 +3037,8 @@ describe('LSP', function() local expected = { { col = 1, + end_col = 1, + end_lnum = 2, filename = '', kind = 'File', lnum = 2, @@ -3038,6 +3046,8 @@ describe('LSP', function() }, { col = 1, + end_col = 1, + end_lnum = 6, filename = '', kind = 'Namespace', lnum = 6, @@ -3111,6 +3121,8 @@ describe('LSP', function() local expected = { { col = 1, + end_col = 1, + end_lnum = 3, filename = '/test_a', kind = 'File', lnum = 2, @@ -3118,6 +3130,8 @@ describe('LSP', function() }, { col = 1, + end_col = 1, + end_lnum = 5, filename = '/test_b', kind = 'Module', lnum = 4,