mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
refactor(lsp): drop str_byteindex/str_utfindex wrappers #30915
* deprecate old signatures * move to new str_byteindex/str_utfindex signature * use single-underscore name (double-underscore is reserved for Lua itself)
This commit is contained in:
parent
b922b7d6d7
commit
25b53b593e
@ -208,6 +208,8 @@ LUA
|
||||
• |vim.fs.rm()| can delete files and directories.
|
||||
• |vim.validate()| now has a new signature which uses less tables,
|
||||
is more peformant and easier to read.
|
||||
• |vim.str_byteindex()| and |vim.str_utfindex()| gained overload signatures
|
||||
supporting two new parameters, `encoding` and `strict_indexing`.
|
||||
|
||||
OPTIONS
|
||||
|
||||
|
@ -305,7 +305,7 @@ local function matchstr(text, pat_or_re)
|
||||
return
|
||||
end
|
||||
|
||||
return text:sub(vim.str_utfindex(text, s) + 1, vim.str_utfindex(text, e))
|
||||
return text:sub(vim.str_utfindex(text, 'utf-32', s) + 1, vim.str_utfindex(text, 'utf-32', e))
|
||||
end
|
||||
|
||||
-- attempt to extract the name and sect out of 'name(sect)'
|
||||
|
@ -545,7 +545,7 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive)
|
||||
-- TODO: handle double-width characters
|
||||
if regtype:byte() == 22 then
|
||||
local bufline = vim.api.nvim_buf_get_lines(bufnr, pos1[1], pos1[1] + 1, true)[1]
|
||||
pos1[2] = vim.str_utfindex(bufline, pos1[2])
|
||||
pos1[2] = vim.str_utfindex(bufline, 'utf-32', pos1[2])
|
||||
end
|
||||
|
||||
local region = {}
|
||||
@ -557,14 +557,14 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive)
|
||||
c2 = c1 + tonumber(regtype:sub(2))
|
||||
-- and adjust for non-ASCII characters
|
||||
local bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1]
|
||||
local utflen = vim.str_utfindex(bufline, #bufline)
|
||||
local utflen = vim.str_utfindex(bufline, 'utf-32', #bufline)
|
||||
if c1 <= utflen then
|
||||
c1 = assert(tonumber(vim.str_byteindex(bufline, c1)))
|
||||
c1 = assert(tonumber(vim.str_byteindex(bufline, 'utf-32', c1)))
|
||||
else
|
||||
c1 = #bufline + 1
|
||||
end
|
||||
if c2 <= utflen then
|
||||
c2 = assert(tonumber(vim.str_byteindex(bufline, c2)))
|
||||
c2 = assert(tonumber(vim.str_byteindex(bufline, 'utf-32', c2)))
|
||||
else
|
||||
c2 = #bufline + 1
|
||||
end
|
||||
@ -740,9 +740,14 @@ function vim.str_byteindex(s, encoding, index, strict_indexing)
|
||||
-- • {str} (`string`)
|
||||
-- • {index} (`integer`)
|
||||
-- • {use_utf16} (`boolean?`)
|
||||
vim.deprecate(
|
||||
'vim.str_byteindex',
|
||||
'vim.str_byteindex(s, encoding, index, strict_indexing)',
|
||||
'1.0'
|
||||
)
|
||||
local old_index = encoding
|
||||
local use_utf16 = index or false
|
||||
return vim.__str_byteindex(s, old_index, use_utf16) or error('index out of range')
|
||||
return vim._str_byteindex(s, old_index, use_utf16) or error('index out of range')
|
||||
end
|
||||
|
||||
vim.validate('s', s, 'string')
|
||||
@ -769,7 +774,7 @@ function vim.str_byteindex(s, encoding, index, strict_indexing)
|
||||
end
|
||||
return index
|
||||
end
|
||||
return vim.__str_byteindex(s, index, encoding == 'utf-16')
|
||||
return vim._str_byteindex(s, index, encoding == 'utf-16')
|
||||
or strict_indexing and error('index out of range')
|
||||
or len
|
||||
end
|
||||
@ -793,8 +798,13 @@ function vim.str_utfindex(s, encoding, index, strict_indexing)
|
||||
-- Parameters: ~
|
||||
-- • {str} (`string`)
|
||||
-- • {index} (`integer?`)
|
||||
vim.deprecate(
|
||||
'vim.str_utfindex',
|
||||
'vim.str_utfindex(s, encoding, index, strict_indexing)',
|
||||
'1.0'
|
||||
)
|
||||
local old_index = encoding
|
||||
local col32, col16 = vim.__str_utfindex(s, old_index) --[[@as integer,integer]]
|
||||
local col32, col16 = vim._str_utfindex(s, old_index) --[[@as integer,integer]]
|
||||
if not col32 or not col16 then
|
||||
error('index out of range')
|
||||
end
|
||||
@ -828,7 +838,7 @@ function vim.str_utfindex(s, encoding, index, strict_indexing)
|
||||
local len = #s
|
||||
return index <= len and index or (strict_indexing and error('index out of range') or len)
|
||||
end
|
||||
local col32, col16 = vim.__str_utfindex(s, index) --[[@as integer?,integer?]]
|
||||
local col32, col16 = vim._str_utfindex(s, index) --[[@as integer?,integer?]]
|
||||
local col = encoding == 'utf-16' and col16 or col32
|
||||
if col then
|
||||
return col
|
||||
@ -836,7 +846,7 @@ function vim.str_utfindex(s, encoding, index, strict_indexing)
|
||||
if strict_indexing then
|
||||
error('index out of range')
|
||||
end
|
||||
local max32, max16 = vim.__str_utfindex(s)--[[@as integer integer]]
|
||||
local max32, max16 = vim._str_utfindex(s)--[[@as integer integer]]
|
||||
return encoding == 'utf-16' and max16 or max32
|
||||
end
|
||||
|
||||
|
@ -1049,7 +1049,7 @@ function lsp.formatexpr(opts)
|
||||
if client.supports_method(ms.textDocument_rangeFormatting) then
|
||||
local params = util.make_formatting_params()
|
||||
local end_line = vim.fn.getline(end_lnum) --[[@as string]]
|
||||
local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding)
|
||||
local end_col = vim.str_utfindex(end_line, client.offset_encoding)
|
||||
--- @cast params +lsp.DocumentRangeFormattingParams
|
||||
params.range = {
|
||||
start = {
|
||||
|
@ -315,7 +315,7 @@ local function adjust_start_col(lnum, line, items, encoding)
|
||||
end
|
||||
end
|
||||
if min_start_char then
|
||||
return lsp.util._str_byteindex_enc(line, min_start_char, encoding)
|
||||
return vim.str_byteindex(line, encoding, min_start_char, false)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
@ -33,25 +33,6 @@ local function severity_vim_to_lsp(severity)
|
||||
return severity
|
||||
end
|
||||
|
||||
---@param lines string[]?
|
||||
---@param lnum integer
|
||||
---@param col integer
|
||||
---@param offset_encoding string
|
||||
---@return integer
|
||||
local function line_byte_from_position(lines, lnum, col, offset_encoding)
|
||||
if not lines or offset_encoding == 'utf-8' then
|
||||
return col
|
||||
end
|
||||
|
||||
local line = lines[lnum + 1]
|
||||
local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == 'utf-16')
|
||||
if ok then
|
||||
return result --- @type integer
|
||||
end
|
||||
|
||||
return col
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@return string[]?
|
||||
local function get_buf_lines(bufnr)
|
||||
@ -118,12 +99,13 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)
|
||||
)
|
||||
message = diagnostic.message.value
|
||||
end
|
||||
local line = buf_lines and buf_lines[start.line + 1] or ''
|
||||
--- @type vim.Diagnostic
|
||||
return {
|
||||
lnum = start.line,
|
||||
col = line_byte_from_position(buf_lines, start.line, start.character, offset_encoding),
|
||||
col = vim.str_byteindex(line, offset_encoding, start.character, false),
|
||||
end_lnum = _end.line,
|
||||
end_col = line_byte_from_position(buf_lines, _end.line, _end.character, offset_encoding),
|
||||
end_col = vim.str_byteindex(line, offset_encoding, _end.character, false),
|
||||
severity = severity_lsp_to_vim(diagnostic.severity),
|
||||
message = message,
|
||||
source = diagnostic.source,
|
||||
|
@ -70,20 +70,12 @@ function M.on_inlayhint(err, result, ctx, _)
|
||||
end
|
||||
|
||||
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
---@param position lsp.Position
|
||||
---@return integer
|
||||
local function pos_to_byte(position)
|
||||
local col = position.character
|
||||
if col > 0 then
|
||||
local line = lines[position.line + 1] or ''
|
||||
return util._str_byteindex_enc(line, col, client.offset_encoding)
|
||||
end
|
||||
return col
|
||||
end
|
||||
|
||||
for _, hint in ipairs(result) do
|
||||
local lnum = hint.position.line
|
||||
hint.position.character = pos_to_byte(hint.position)
|
||||
local line = lines and lines[lnum + 1] or ''
|
||||
hint.position.character =
|
||||
vim.str_byteindex(line, client.offset_encoding, hint.position.character, false)
|
||||
table.insert(new_lnum_hints[lnum], hint)
|
||||
end
|
||||
|
||||
|
@ -137,16 +137,10 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
||||
local token_type = token_types[data[i + 3] + 1]
|
||||
local modifiers = modifiers_from_number(data[i + 4], token_modifiers)
|
||||
|
||||
local function _get_byte_pos(col)
|
||||
if col > 0 then
|
||||
local buf_line = lines[line + 1] or ''
|
||||
return util._str_byteindex_enc(buf_line, col, client.offset_encoding)
|
||||
end
|
||||
return col
|
||||
end
|
||||
|
||||
local start_col = _get_byte_pos(start_char)
|
||||
local end_col = _get_byte_pos(start_char + data[i + 2])
|
||||
local end_char = start_char + data[i + 2]
|
||||
local buf_line = lines and lines[line + 1] or ''
|
||||
local start_col = vim.str_byteindex(buf_line, client.offset_encoding, start_char, false)
|
||||
local end_col = vim.str_byteindex(buf_line, client.offset_encoding, end_char, false)
|
||||
|
||||
if token_type then
|
||||
ranges[#ranges + 1] = {
|
||||
|
@ -48,45 +48,6 @@ local str_utfindex = vim.str_utfindex
|
||||
local str_utf_start = vim.str_utf_start
|
||||
local str_utf_end = vim.str_utf_end
|
||||
|
||||
-- Given a line, byte idx, and offset_encoding convert to the
|
||||
-- utf-8, utf-16, or utf-32 index.
|
||||
---@param line string the line to index into
|
||||
---@param byte integer the byte idx
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8)
|
||||
---@return integer utf_idx for the given encoding
|
||||
local function byte_to_utf(line, byte, offset_encoding)
|
||||
-- convert to 0 based indexing for str_utfindex
|
||||
byte = byte - 1
|
||||
|
||||
local utf_idx, _ --- @type integer, integer
|
||||
-- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based
|
||||
if offset_encoding == 'utf-16' then
|
||||
_, utf_idx = str_utfindex(line, byte)
|
||||
elseif offset_encoding == 'utf-32' then
|
||||
utf_idx, _ = str_utfindex(line, byte)
|
||||
else
|
||||
utf_idx = byte
|
||||
end
|
||||
|
||||
-- convert to 1 based indexing
|
||||
return utf_idx + 1
|
||||
end
|
||||
|
||||
---@param line string
|
||||
---@param offset_encoding string
|
||||
---@return integer
|
||||
local function compute_line_length(line, offset_encoding)
|
||||
local length, _ --- @type integer, integer
|
||||
if offset_encoding == 'utf-16' then
|
||||
_, length = str_utfindex(line)
|
||||
elseif offset_encoding == 'utf-32' then
|
||||
length, _ = str_utfindex(line)
|
||||
else
|
||||
length = #line
|
||||
end
|
||||
return length
|
||||
end
|
||||
|
||||
-- Given a line, byte idx, alignment, and offset_encoding convert to the aligned
|
||||
-- utf-8 index and either the utf-16, or utf-32 index.
|
||||
---@param line string the line to index into
|
||||
@ -101,7 +62,7 @@ local function align_end_position(line, byte, offset_encoding)
|
||||
char = byte
|
||||
-- Called in the case of extending an empty line "" -> "a"
|
||||
elseif byte == #line + 1 then
|
||||
char = compute_line_length(line, offset_encoding) + 1
|
||||
char = str_utfindex(line, offset_encoding) + 1
|
||||
else
|
||||
-- Modifying line, find the nearest utf codepoint
|
||||
local offset = str_utf_start(line, byte)
|
||||
@ -111,9 +72,10 @@ local function align_end_position(line, byte, offset_encoding)
|
||||
byte = byte + str_utf_end(line, byte) + 1
|
||||
end
|
||||
if byte <= #line then
|
||||
char = byte_to_utf(line, byte, offset_encoding)
|
||||
--- Convert to 0 based for input, and from 0 based for output
|
||||
char = str_utfindex(line, offset_encoding, byte - 1) + 1
|
||||
else
|
||||
char = compute_line_length(line, offset_encoding) + 1
|
||||
char = str_utfindex(line, offset_encoding) + 1
|
||||
end
|
||||
-- Extending line, find the nearest utf codepoint for the last valid character
|
||||
end
|
||||
@ -153,7 +115,7 @@ local function compute_start_range(
|
||||
if line then
|
||||
line_idx = firstline - 1
|
||||
byte_idx = #line + 1
|
||||
char_idx = compute_line_length(line, offset_encoding) + 1
|
||||
char_idx = str_utfindex(line, offset_encoding) + 1
|
||||
else
|
||||
line_idx = firstline
|
||||
byte_idx = 1
|
||||
@ -190,10 +152,11 @@ local function compute_start_range(
|
||||
char_idx = 1
|
||||
elseif start_byte_idx == #prev_line + 1 then
|
||||
byte_idx = start_byte_idx
|
||||
char_idx = compute_line_length(prev_line, offset_encoding) + 1
|
||||
char_idx = str_utfindex(prev_line, offset_encoding) + 1
|
||||
else
|
||||
byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx)
|
||||
char_idx = byte_to_utf(prev_line, byte_idx, offset_encoding)
|
||||
--- Convert to 0 based for input, and from 0 based for output
|
||||
char_idx = vim.str_utfindex(prev_line, offset_encoding, byte_idx - 1) + 1
|
||||
end
|
||||
|
||||
-- Return the start difference (shared for new and prev lines)
|
||||
@ -230,7 +193,7 @@ local function compute_end_range(
|
||||
return {
|
||||
line_idx = lastline - 1,
|
||||
byte_idx = #prev_line + 1,
|
||||
char_idx = compute_line_length(prev_line, offset_encoding) + 1,
|
||||
char_idx = str_utfindex(prev_line, offset_encoding) + 1,
|
||||
}, { line_idx = 1, byte_idx = 1, char_idx = 1 }
|
||||
end
|
||||
-- If firstline == new_lastline, the first change occurred on a line that was deleted.
|
||||
@ -376,7 +339,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi
|
||||
local start_line = lines[start_range.line_idx]
|
||||
local range_length --- @type integer
|
||||
if start_line and #start_line > 0 then
|
||||
range_length = compute_line_length(start_line, offset_encoding)
|
||||
range_length = str_utfindex(start_line, offset_encoding)
|
||||
- start_range.char_idx
|
||||
+ 1
|
||||
+ line_ending_length
|
||||
@ -389,7 +352,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi
|
||||
for idx = start_range.line_idx + 1, end_range.line_idx - 1 do
|
||||
-- Length full line plus newline character
|
||||
if #lines[idx] > 0 then
|
||||
range_length = range_length + compute_line_length(lines[idx], offset_encoding) + #line_ending
|
||||
range_length = range_length + str_utfindex(lines[idx], offset_encoding) + #line_ending
|
||||
else
|
||||
range_length = range_length + line_ending_length
|
||||
end
|
||||
|
@ -116,71 +116,6 @@ local function create_window_without_focus()
|
||||
return new
|
||||
end
|
||||
|
||||
--- Convert byte index to `encoding` index.
|
||||
--- Convenience wrapper around vim.str_utfindex
|
||||
---@param line string line to be indexed
|
||||
---@param index integer? byte index (utf-8), or `nil` for length
|
||||
---@param encoding 'utf-8'|'utf-16'|'utf-32'? defaults to utf-16
|
||||
---@return integer `encoding` index of `index` in `line`
|
||||
function M._str_utfindex_enc(line, index, encoding)
|
||||
local len32, len16 = vim.str_utfindex(line)
|
||||
if not encoding then
|
||||
encoding = 'utf-16'
|
||||
end
|
||||
if encoding == 'utf-8' then
|
||||
if index then
|
||||
return index
|
||||
else
|
||||
return #line
|
||||
end
|
||||
elseif encoding == 'utf-16' then
|
||||
if not index or index > len16 then
|
||||
return len16
|
||||
end
|
||||
local _, col16 = vim.str_utfindex(line, index)
|
||||
return col16
|
||||
elseif encoding == 'utf-32' then
|
||||
if not index or index > len32 then
|
||||
return len32
|
||||
end
|
||||
local col32, _ = vim.str_utfindex(line, index)
|
||||
return col32
|
||||
else
|
||||
error('Invalid encoding: ' .. vim.inspect(encoding))
|
||||
end
|
||||
end
|
||||
|
||||
--- Convert UTF index to `encoding` index.
|
||||
--- Convenience wrapper around vim.str_byteindex
|
||||
---Alternative to vim.str_byteindex that takes an encoding.
|
||||
---@param line string line to be indexed
|
||||
---@param index integer UTF index
|
||||
---@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`
|
||||
function M._str_byteindex_enc(line, index, encoding)
|
||||
-- LSP spec: if character > line length, default to the line length.
|
||||
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
|
||||
local len8 = #line
|
||||
if not encoding then
|
||||
encoding = 'utf-16'
|
||||
end
|
||||
if encoding == 'utf-8' then
|
||||
if index and index <= len8 then
|
||||
return index
|
||||
else
|
||||
return len8
|
||||
end
|
||||
end
|
||||
local len32, len16 = vim.str_utfindex(line)
|
||||
if encoding == 'utf-16' then
|
||||
return index <= len16 and vim.str_byteindex(line, index, true) or len8
|
||||
elseif encoding == 'utf-32' then
|
||||
return index <= len32 and vim.str_byteindex(line, index) or len8
|
||||
else
|
||||
error('Invalid encoding: ' .. vim.inspect(encoding))
|
||||
end
|
||||
end
|
||||
|
||||
--- Replaces text in a range with new text.
|
||||
---
|
||||
--- CAUTION: Changes in-place!
|
||||
@ -352,7 +287,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
-- character
|
||||
if col > 0 then
|
||||
local line = get_line(bufnr, position.line) or ''
|
||||
return M._str_byteindex_enc(line, col, offset_encoding)
|
||||
return vim.str_byteindex(line, offset_encoding, col, false)
|
||||
end
|
||||
return col
|
||||
end
|
||||
@ -1787,8 +1722,8 @@ function M.locations_to_items(locations, offset_encoding)
|
||||
local end_row = end_pos.line
|
||||
local line = lines[row] or ''
|
||||
local end_line = lines[end_row] or ''
|
||||
local col = M._str_byteindex_enc(line, pos.character, offset_encoding)
|
||||
local end_col = M._str_byteindex_enc(end_line, end_pos.character, offset_encoding)
|
||||
local col = vim.str_byteindex(line, offset_encoding, pos.character, false)
|
||||
local end_col = vim.str_byteindex(end_line, offset_encoding, end_pos.character, false)
|
||||
|
||||
items[#items + 1] = {
|
||||
filename = filename,
|
||||
@ -1911,7 +1846,7 @@ local function make_position_param(window, offset_encoding)
|
||||
return { line = 0, character = 0 }
|
||||
end
|
||||
|
||||
col = M._str_utfindex_enc(line, col, offset_encoding)
|
||||
col = vim.str_utfindex(line, offset_encoding, col, false)
|
||||
|
||||
return { line = row, character = col }
|
||||
end
|
||||
@ -2092,7 +2027,7 @@ function M.character_offset(buf, row, col, offset_encoding)
|
||||
)
|
||||
offset_encoding = vim.lsp.get_clients({ bufnr = buf })[1].offset_encoding
|
||||
end
|
||||
return M._str_utfindex_enc(line, col, offset_encoding)
|
||||
return vim.str_utfindex(line, offset_encoding, col, false)
|
||||
end
|
||||
|
||||
--- Helper function to return nested values in language server settings
|
||||
|
@ -699,10 +699,10 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
|
||||
lua_setfield(lstate, -2, "stricmp");
|
||||
// str_utfindex
|
||||
lua_pushcfunction(lstate, &nlua_str_utfindex);
|
||||
lua_setfield(lstate, -2, "__str_utfindex");
|
||||
lua_setfield(lstate, -2, "_str_utfindex");
|
||||
// str_byteindex
|
||||
lua_pushcfunction(lstate, &nlua_str_byteindex);
|
||||
lua_setfield(lstate, -2, "__str_byteindex");
|
||||
lua_setfield(lstate, -2, "_str_byteindex");
|
||||
// str_utf_pos
|
||||
lua_pushcfunction(lstate, &nlua_str_utf_pos);
|
||||
lua_setfield(lstate, -2, "str_utf_pos");
|
||||
|
@ -219,13 +219,13 @@ describe('vim.lsp.diagnostic', function()
|
||||
eq(1, #result)
|
||||
eq(
|
||||
exec_lua(function()
|
||||
return vim.str_byteindex(line, 7, true)
|
||||
return vim.str_byteindex(line, 'utf-16', 7)
|
||||
end),
|
||||
result[1].col
|
||||
)
|
||||
eq(
|
||||
exec_lua(function()
|
||||
return vim.str_byteindex(line, 8, true)
|
||||
return vim.str_byteindex(line, 'utf-16', 8)
|
||||
end),
|
||||
result[1].end_col
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user