diff options
author | Yi Ming <ofseed@foxmail.com> | 2024-11-21 04:19:07 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-20 12:19:07 -0800 |
commit | 629483e24eed3f2c07e55e0540c553361e0345a2 (patch) | |
tree | 0ac4969929cef4cdc272362bf8e6d01c40669179 | |
parent | 1b6442034f6a821d357fe59cd75fdae47a7f7cff (diff) | |
download | rneovim-629483e24eed3f2c07e55e0540c553361e0345a2.tar.gz rneovim-629483e24eed3f2c07e55e0540c553361e0345a2.tar.bz2 rneovim-629483e24eed3f2c07e55e0540c553361e0345a2.zip |
feat(lsp): require `offset_encoding` param #31249
Problem:
Since [version 3.17](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocuments),
LSP supports specifying the position encoding (aka offset encoding) supported by
the client through `positionEncoding`. Since #31209, Nvim fully supports
`utf-8`, `utf-16`, and `utf-32` encodings.
Previously, nvim assumed all clients for a buffer had the same
`offset_encoding`, so:
* Nvim provides `vim.lsp._get_offset_encoding()` to get `offset_encoding`, but
this function is incorrect because `offset_encoding` is per-client, not
per-buffer.
* Based on the strategy of `vim.lsp._get_offset_encoding()`,
`vim.lsp.util.make_position_params()`, `vim.lsp.util.make_range_params()`, and
`vim.lsp.util.make_given_range_params()` do not require the caller to pass
`offset_encoding`, which is invalid.
* https://github.com/neovim/neovim/issues/25272
Solution:
* Mark `vim.lsp._get_offset_encoding()` as `@deprecated`.
* Change the type annotations of `vim.lsp.util.make_position_params()`,
`vim.lsp.util.make_range_params()`, `vim.lsp.util.make_given_range_params()`
to require the `offset_encoding` param.
-rw-r--r-- | runtime/doc/lsp.txt | 17 | ||||
-rw-r--r-- | runtime/doc/news.txt | 3 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 42 |
3 files changed, 37 insertions, 25 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index ae26abd34d..3cb3e590f4 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -2025,12 +2025,10 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding}) selection. • {bufnr} (`integer?`) buffer handle or 0 for current, defaults to current - • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) defaults to - `offset_encoding` of first client of `bufnr` + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'`) Return: ~ - (`table`) { textDocument = { uri = `current_file_uri` }, range = { - start = `start_position`, end = `end_position` } } + (`{ textDocument: { uri: lsp.DocumentUri }, range: lsp.Range }`) *vim.lsp.util.make_position_params()* make_position_params({window}, {offset_encoding}) @@ -2040,9 +2038,7 @@ make_position_params({window}, {offset_encoding}) Parameters: ~ • {window} (`integer?`) window handle or 0 for current, defaults to current - • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) defaults to - `offset_encoding` of first client of buffer of - `window` + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'`) Return: ~ (`lsp.TextDocumentPositionParams`) @@ -2060,13 +2056,10 @@ make_range_params({window}, {offset_encoding}) Parameters: ~ • {window} (`integer?`) window handle or 0 for current, defaults to current - • {offset_encoding} (`"utf-8"|"utf-16"|"utf-32"?`) defaults to - `offset_encoding` of first client of buffer of - `window` + • {offset_encoding} (`"utf-8"|"utf-16"|"utf-32"`) Return: ~ - (`table`) { textDocument = { uri = `current_file_uri` }, range = { - start = `current_position`, end = `current_position` } } + (`{ textDocument: { uri: lsp.DocumentUri }, range: lsp.Range }`) *vim.lsp.util.make_text_document_params()* make_text_document_params({bufnr}) diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 32deb85278..f3d82786bd 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -95,6 +95,9 @@ LSP Instead use: >lua vim.diagnostic.config(config, vim.lsp.diagnostic.get_namespace(client_id)) < +• |vim.lsp.util.make_position_params()|, |vim.lsp.util.make_range_params()| + and |vim.lsp.util.make_given_range_params()| now require the `offset_encoding` + parameter. LUA diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 9e352dbcfd..cfa8a194d9 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1848,12 +1848,11 @@ function M.try_trim_markdown_code_blocks(lines) end ---@param window integer?: window handle or 0 for current, defaults to current ----@param offset_encoding? 'utf-8'|'utf-16'|'utf-32'? defaults to `offset_encoding` of first client of buffer of `window` +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' local function make_position_param(window, offset_encoding) window = window or 0 local buf = api.nvim_win_get_buf(window) local row, col = unpack(api.nvim_win_get_cursor(window)) - offset_encoding = offset_encoding or M._get_offset_encoding(buf) row = row - 1 local line = api.nvim_buf_get_lines(buf, row, row + 1, true)[1] if not line then @@ -1868,13 +1867,19 @@ end --- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position. --- ---@param window integer?: window handle or 0 for current, defaults to current ----@param offset_encoding 'utf-8'|'utf-16'|'utf-32'? defaults to `offset_encoding` of first client of buffer of `window` +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' ---@return lsp.TextDocumentPositionParams ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams function M.make_position_params(window, offset_encoding) window = window or 0 local buf = api.nvim_win_get_buf(window) - offset_encoding = offset_encoding or M._get_offset_encoding(buf) + if offset_encoding == nil then + vim.notify_once( + 'warning: offset_encoding is required, using the offset_encoding from the first client', + vim.log.levels.WARN + ) + offset_encoding = M._get_offset_encoding(buf) + end return { textDocument = M.make_text_document_params(buf), position = make_position_param(window, offset_encoding), @@ -1882,6 +1887,7 @@ function M.make_position_params(window, offset_encoding) end --- Utility function for getting the encoding of the first LSP client on the given buffer. +---@deprecated ---@param bufnr integer buffer handle or 0 for current, defaults to current ---@return string encoding first client if there is one, nil otherwise function M._get_offset_encoding(bufnr) @@ -1904,7 +1910,7 @@ function M._get_offset_encoding(bufnr) offset_encoding = this_offset_encoding elseif offset_encoding ~= this_offset_encoding then vim.notify_once( - 'warning: multiple different client offset_encodings detected for buffer, this is not supported yet', + 'warning: multiple different client offset_encodings detected for buffer, vim.lsp.util._get_offset_encoding() uses the offset_encoding from the first client', vim.log.levels.WARN ) end @@ -1919,12 +1925,17 @@ end --- `textDocument/rangeFormatting`. --- ---@param window integer? window handle or 0 for current, defaults to current ----@param offset_encoding "utf-8"|"utf-16"|"utf-32"? defaults to `offset_encoding` of first client of buffer of `window` ----@return table { textDocument = { uri = `current_file_uri` }, range = { start = ----`current_position`, end = `current_position` } } +---@param offset_encoding "utf-8"|"utf-16"|"utf-32" +---@return { textDocument: { uri: lsp.DocumentUri }, range: lsp.Range } function M.make_range_params(window, offset_encoding) local buf = api.nvim_win_get_buf(window or 0) - offset_encoding = offset_encoding or M._get_offset_encoding(buf) + if offset_encoding == nil then + vim.notify_once( + 'warning: offset_encoding is required, using the offset_encoding from the first client', + vim.log.levels.WARN + ) + offset_encoding = M._get_offset_encoding(buf) + end local position = make_position_param(window, offset_encoding) return { textDocument = M.make_text_document_params(buf), @@ -1940,15 +1951,20 @@ end ---@param end_pos [integer,integer]? {row,col} mark-indexed position. --- Defaults to the end of the last visual selection. ---@param bufnr integer? buffer handle or 0 for current, defaults to current ----@param offset_encoding 'utf-8'|'utf-16'|'utf-32'? defaults to `offset_encoding` of first client of `bufnr` ----@return table { textDocument = { uri = `current_file_uri` }, range = { start = ----`start_position`, end = `end_position` } } +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' +---@return { textDocument: { uri: lsp.DocumentUri }, range: lsp.Range } function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding) validate('start_pos', start_pos, 'table', true) validate('end_pos', end_pos, 'table', true) validate('offset_encoding', offset_encoding, 'string', true) bufnr = bufnr or api.nvim_get_current_buf() - offset_encoding = offset_encoding or M._get_offset_encoding(bufnr) + if offset_encoding == nil then + vim.notify_once( + 'warning: offset_encoding is required, using the offset_encoding from the first client', + vim.log.levels.WARN + ) + offset_encoding = M._get_offset_encoding(bufnr) + end --- @type [integer, integer] local A = { unpack(start_pos or api.nvim_buf_get_mark(bufnr, '<')) } --- @type [integer, integer] |