fix(pos): get_lines() return empty table when file opening fails

Problem:
`get_lines()` may returns empty table when file opening fails,
so every existing caller use `get_line() or ''` to avoid nil result.

This also does not match the annotated return type of `get_line()`,
which is `string` instead of `string?`.

Solution:
Make `get_line()` return empty string when file opening fails.
This commit is contained in:
Yi Ming
2026-06-02 18:14:24 +08:00
parent 5beb751ef5
commit 241a725e17
2 changed files with 21 additions and 35 deletions

View File

@@ -224,7 +224,7 @@ function M.apply_text_edits(text_edits, bufnr, position_encoding, change_annotat
if max <= start_row then
api.nvim_buf_set_lines(bufnr, max, max, false, text)
else
local last_line_len = #(get_line(bufnr, math.min(end_row, max - 1)) or '')
local last_line_len = #get_line(bufnr, math.min(end_row, max - 1))
-- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't
-- accept it so we should fix it here.
if max <= end_row then
@@ -325,7 +325,7 @@ function M.apply_text_edits(text_edits, bufnr, position_encoding, change_annotat
if pos then
-- make sure we don't go out of bounds
pos[1] = math.min(pos[1], max)
pos[2] = math.min(pos[2], #(get_line(bufnr, pos[1] - 1) or ''))
pos[2] = math.min(pos[2], #get_line(bufnr, pos[1] - 1))
api.nvim_buf_set_mark(bufnr or 0, mark, pos[1], pos[2], {})
end
end
@@ -1723,8 +1723,8 @@ function M.locations_to_items(locations, position_encoding)
local end_pos = temp['end']
local row = pos.line
local end_row = end_pos.line
local line = lines[row] or ''
local end_line = lines[end_row] or ''
local line = lines[row]
local end_line = lines[end_row]
local col = vim.str_byteindex(line, position_encoding, pos.character, false)
local end_col = vim.str_byteindex(end_line, position_encoding, end_pos.character, false)

View File

@@ -88,44 +88,30 @@ function M.get_lines(buf, rows)
return buf_lines()
end
local row_line = {} --- @type table<integer, string>
for _, row in pairs(rows) do
row_line[row] = ''
end
-- Get the data from the file.
local success, data = pcall(vim.fn.readblob, vim.api.nvim_buf_get_name(buf))
if not success then
return {}
return row_line
end
local row_line = {} --- @type table<integer,true|string> rows we need to retrieve
local need = 0 -- Keep track of how many unique rows we need.
for _, row in pairs(rows) do
if not row_line[row] then
need = need + 1
end
row_line[row] = true
end
do
local found = 0
local row = 0
for line in string.gmatch(data, '([^\n]*)\n?') do
if row_line[row] == true then
row_line[row] = line
found = found + 1
if found == need then
break
end
local need = vim.tbl_count(row_line)
local row = 0
for line in string.gmatch(data, '([^\n]*)\n?') do
if row_line[row] then
row_line[row] = line
need = need - 1
if need == 0 then
break
end
row = row + 1
end
row = row + 1
end
-- Change any lines we didn't find to the empty string.
for row, line in pairs(row_line) do
if line == true then
row_line[row] = ''
end
end
return row_line --[[@as table<integer,string>]]
return row_line
end
--- Gets the zero-indexed line from the given buffer.
@@ -169,7 +155,7 @@ function M.from_lsp(buf, position, position_encoding)
if col > 0 then
-- `strict_indexing` is disabled, because LSP responses are asynchronous,
-- and the buffer content may have changed, causing out-of-bounds errors.
col = vim.str_byteindex(M.get_line(buf, row) or '', position_encoding, col, false)
col = vim.str_byteindex(M.get_line(buf, row), position_encoding, col, false)
end
return row, col
end