From 554b21261ec0ad1eaac7afc21d9a1ba7fb7cabf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Fu=C3=9Fenegger?= Date: Tue, 30 Jun 2020 17:48:04 +0200 Subject: [PATCH] lsp: Use nvim_buf_get_lines in locations_to_items and add more tests (#12357) * LSP: Add tests & use nvim_buf_get_lines in locations_to_items This is to add support for cases where the server returns a URI in the locations that does not have a file scheme but needs to be loaded via a BufReadCmd event. * LSP: Don't iterate through all lines in locations_to_items * fixup! LSP: Don't iterate through all lines in locations_to_items * fixup! fixup! LSP: Don't iterate through all lines in locations_to_items * fixup! fixup! fixup! LSP: Don't iterate through all lines in locations_to_items --- runtime/lua/vim/lsp/util.lua | 43 +++++++++------------ test/functional/plugin/lsp_spec.lua | 58 +++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 26 deletions(-) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 4176255eb6..ab2992ba60 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1089,40 +1089,31 @@ function M.locations_to_items(locations) for _, d in ipairs(locations) do -- locations may be Location or LocationLink local uri = d.uri or d.targetUri - local fname = assert(vim.uri_to_fname(uri)) local range = d.range or d.targetSelectionRange - table.insert(grouped[fname], {start = range.start}) + table.insert(grouped[uri], {start = range.start}) end local keys = vim.tbl_keys(grouped) table.sort(keys) -- TODO(ashkan) I wish we could do this lazily. - for _, fname in ipairs(keys) do - local rows = grouped[fname] - + for _, uri in ipairs(keys) do + local rows = grouped[uri] table.sort(rows, position_sort) - local i = 0 - for line in io.lines(fname) do - for _, temp in ipairs(rows) do - local pos = temp.start - local row = pos.line - if i == row then - local col - if pos.character > #line then - col = #line - else - col = vim.str_byteindex(line, pos.character) - end - table.insert(items, { - filename = fname, - lnum = row + 1, - col = col + 1; - text = line; - }) - end - end - i = i + 1 + local bufnr = vim.uri_to_bufnr(uri) + vim.fn.bufload(bufnr) + local filename = vim.uri_to_fname(uri) + for _, temp in ipairs(rows) do + local pos = temp.start + local row = pos.line + local line = (api.nvim_buf_get_lines(bufnr, row, row + 1, false) or {""})[1] + local col = M.character_offset(bufnr, row, pos.character) + table.insert(items, { + filename = filename, + lnum = row + 1, + col = col + 1; + text = line; + }) end end return items diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 4b12ea2557..1b022f50df 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -1070,6 +1070,64 @@ describe('LSP', function() ]]) end) end) + describe('lsp.util.locations_to_items', function() + it('Convert Location[] to items', function() + local expected = { + { + filename = 'fake/uri', + lnum = 1, + col = 3, + text = 'testing' + }, + } + local actual = exec_lua [[ + 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 = { + { + uri = 'file://fake/uri', + range = { + start = { line = 0, character = 2 }, + ['end'] = { line = 0, character = 3 }, + } + }, + } + return vim.lsp.util.locations_to_items(locations) + ]] + eq(expected, actual) + end) + it('Convert LocationLink[] to items', function() + local expected = { + { + filename = 'fake/uri', + lnum = 1, + col = 3, + text = 'testing' + }, + } + local actual = exec_lua [[ + 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 = { + { + targetUri = vim.uri_from_bufnr(bufnr), + targetRange = { + start = { line = 0, character = 2 }, + ['end'] = { line = 0, character = 3 }, + }, + targetSelectionRange = { + start = { line = 0, character = 2 }, + ['end'] = { line = 0, character = 3 }, + } + }, + } + return vim.lsp.util.locations_to_items(locations) + ]] + eq(expected, actual) + end) + end) describe('lsp.util.symbols_to_items', function() describe('convert DocumentSymbol[] to items', function() it('DocumentSymbol has children', function()