aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/util.lua
diff options
context:
space:
mode:
authorFolke Lemaitre <folke.lemaitre@gmail.com>2021-05-22 13:04:53 +0200
committerFolke Lemaitre <folke.lemaitre@gmail.com>2021-05-22 18:56:48 +0200
commitc98e4d1a2ab700f563740c033abfc1fe1c955637 (patch)
tree68bbf48ba2169003ffb0b403a1bd43e95031f21a /runtime/lua/vim/lsp/util.lua
parent6dd04ed5f6c0b68eed38aeb2a3f930d8d6353678 (diff)
downloadrneovim-c98e4d1a2ab700f563740c033abfc1fe1c955637.tar.gz
rneovim-c98e4d1a2ab700f563740c033abfc1fe1c955637.tar.bz2
rneovim-c98e4d1a2ab700f563740c033abfc1fe1c955637.zip
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.lua46
1 files changed, 42 insertions, 4 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 2ae9be57c0..aab57a2d0a 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,