diff options
author | Michael Lingelbach <m.j.lbach@gmail.com> | 2021-05-22 10:58:45 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-22 10:58:45 -0700 |
commit | 0cbe748da34dbbd8c4db4914c9f87c500640c267 (patch) | |
tree | 5cce74a20c2e48c2fd84ff01e20424cf9918e768 /runtime/lua/vim/lsp/util.lua | |
parent | 5b2be75256b638275900be0b36ee02ef1730f999 (diff) | |
parent | c98e4d1a2ab700f563740c033abfc1fe1c955637 (diff) | |
download | rneovim-0cbe748da34dbbd8c4db4914c9f87c500640c267.tar.gz rneovim-0cbe748da34dbbd8c4db4914c9f87c500640c267.tar.bz2 rneovim-0cbe748da34dbbd8c4db4914c9f87c500640c267.zip |
Merge pull request #14615 from folke/faster_locations_to_items
perf(lsp): `locations_to_items`: use libuv for unloaded buffers to get line
Diffstat (limited to 'runtime/lua/vim/lsp/util.lua')
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 01fa22999a..7809c9b7e3 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -4,6 +4,7 @@ local validate = vim.validate local api = vim.api local list_extend = vim.list_extend local highlight = require 'vim.highlight' +local uv = vim.loop local npcall = vim.F.npcall local split = vim.split @@ -1361,6 +1362,45 @@ local position_sort = sort_by_key(function(v) return {v.start.line, v.start.character} end) +-- Gets the zero-indexed line from the given uri. +-- For non-file uris, we load the buffer and get the line. +-- If a loaded buffer exists, then that is used. +-- Otherwise we get the line using libuv which is a lot faster than loading the buffer. +--@param uri string uri of the resource to get the line from +--@param row number zero-indexed line number +--@return string the line at row in filename +function M.get_line(uri, row) + -- load the buffer if this is not a file uri + -- Custom language server protocol extensions can result in servers sending URIs with custom schemes. Plugins are able to load these via `BufReadCmd` autocmds. + if uri:sub(1, 4) ~= "file" then + local bufnr = vim.uri_to_bufnr(uri) + vim.fn.bufload(bufnr) + return (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { "" })[1] + end + + local filename = vim.uri_to_fname(uri) + + -- use loaded buffers if available + if vim.fn.bufloaded(filename) == 1 then + local bufnr = vim.fn.bufnr(filename, false) + return (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { "" })[1] + end + + local fd = uv.fs_open(filename, "r", 438) + -- TODO: what should we do in this case? + if not fd then return "" end + local stat = uv.fs_fstat(fd) + local data = uv.fs_read(fd, stat.size, 0) + uv.fs_close(fd) + + local lnum = 0 + for line in string.gmatch(data, "([^\n]*)\n?") do + if lnum == row then return line end + lnum = lnum + 1 + end + return "" +end + --- Returns the items with the byte position calculated correctly and in sorted --- order, for display in quickfix and location lists. --- @@ -1389,14 +1429,12 @@ function M.locations_to_items(locations) for _, uri in ipairs(keys) do local rows = grouped[uri] table.sort(rows, position_sort) - 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) + local line = M.get_line(uri, row) + local col = pos.character table.insert(items, { filename = filename, lnum = row + 1, |