fix(lsp): handle nil bytes in strings

Problem:

The LSP omnifunc can insert nil bytes, which when read in other places
(like semantic token) could cause an error:

    semantic_tokens.lua:304: Vim:E976: Using a Blob as a String

Solution:

Use `#line` instead of `vim.fn.strlen(line)`. Both return UTF-8 bytes
but the latter can't handle nil bytes.

Completion candidates can currently insert nil bytes, if other parts of
Alternative fix to https://github.com/neovim/neovim/pull/30359

Note that https://github.com/neovim/neovim/pull/30315 will avoid the
insertion of nil bytes from the LSP omnifunc, but the change of this PR
can more easily be backported.
This commit is contained in:
Mathias Fussenegger 2024-09-13 19:57:04 +02:00 committed by Mathias Fußenegger
parent 755512ed60
commit 8512f669f0

View File

@ -154,7 +154,7 @@ end
---@param encoding string utf-8|utf-16|utf-32| defaults to utf-16 ---@param encoding string utf-8|utf-16|utf-32| defaults to utf-16
---@return integer byte (utf-8) index of `encoding` index `index` in `line` ---@return integer byte (utf-8) index of `encoding` index `index` in `line`
function M._str_byteindex_enc(line, index, encoding) function M._str_byteindex_enc(line, index, encoding)
local len = vim.fn.strlen(line) local len = #line
if index > len then if index > len then
-- LSP spec: if character > line length, default to the line length. -- LSP spec: if character > line length, default to the line length.
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position -- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
@ -167,7 +167,7 @@ function M._str_byteindex_enc(line, index, encoding)
if index then if index then
return index return index
else else
return #line return len
end end
elseif encoding == 'utf-16' then elseif encoding == 'utf-16' then
return vim.str_byteindex(line, index, true) return vim.str_byteindex(line, index, true)