feat(lsp): add range option to code_action; deprecate range_code_action (#19551)

`code_action` gained extra functions (`filter` and `apply`) which
`range_code_action` didn't have.

To close this gap, this adds a `range` option to `code_action` and
deprecates `range_code_action`.

The option defaults to the current selection if in visual mode.
This allows users to setup a mapping like `vim.keymap.set({'v', 'n'},
'<a-CR>', vim.lsp.buf.code_action)`

`range_code_action` used to use the `<` and `>` markers to get the
_last_ selection which required using a `<Esc><Cmd>lua
vim.lsp.buf.range_code_action()<CR>` (note the `<ESC>`) mapping.
This commit is contained in:
Mathias Fußenegger
2022-07-28 19:19:07 +02:00
committed by GitHub
parent 468b1a689a
commit 98915f88b2
3 changed files with 94 additions and 55 deletions

View File

@@ -1096,7 +1096,7 @@ code_action({options}) *vim.lsp.buf.code_action()*
Parameters: ~ Parameters: ~
{options} (table|nil) Optional table which holds the {options} (table|nil) Optional table which holds the
following optional fields: following optional fields:
• context (table|nil): Corresponds to `CodeActionContext` of the LSP specification: • context: (table|nil) Corresponds to `CodeActionContext` of the LSP specification:
• diagnostics (table|nil): LSP`Diagnostic[]` . Inferred from the current position if not • diagnostics (table|nil): LSP`Diagnostic[]` . Inferred from the current position if not
provided. provided.
• only (table|nil): List of LSP • only (table|nil): List of LSP
@@ -1104,13 +1104,18 @@ code_action({options}) *vim.lsp.buf.code_action()*
actions. Most language servers support actions. Most language servers support
values like `refactor` or `quickfix`. values like `refactor` or `quickfix`.
• filter (function|nil): Predicate function • filter: (function|nil) Predicate taking an
taking an `CodeAction` and returning a `CodeAction` and returning a boolean.
boolean. • apply: (boolean|nil) When set to `true`, and
• apply (boolean|nil): When set to `true`, and
there is just one remaining action (after there is just one remaining action (after
filtering), the action is applied without filtering), the action is applied without
user query. user query.
• range: (table|nil) Range for which code
actions should be requested. If in visual
mode this defaults to the active selection.
Table must contain `start` and `end` keys
with {row, col} tuples using mark-like
indexing. See |api-indexing|
See also: ~ See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
@@ -1606,7 +1611,7 @@ character_offset({buf}, {row}, {col}, {offset_encoding})
certain buffer. certain buffer.
Parameters: ~ Parameters: ~
{buf} buffer id (0 for current) {buf} (number) buffer number (0 for current)
{row} 0-indexed line {row} 0-indexed line
{col} 0-indexed byte offset in line {col} 0-indexed byte offset in line
{offset_encoding} (string) utf-8|utf-16|utf-32|nil {offset_encoding} (string) utf-8|utf-16|utf-32|nil
@@ -1768,17 +1773,17 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding})
that is similar to |vim.lsp.util.make_range_params()|. that is similar to |vim.lsp.util.make_range_params()|.
Parameters: ~ Parameters: ~
{start_pos} ({number, number}, optional) {start_pos} number[]|nil {row, col} mark-indexed
mark-indexed position. Defaults to the position. Defaults to the start of the
start of the last visual selection. last visual selection.
{end_pos} ({number, number}, optional) {end_pos} number[]|nil {row, col} mark-indexed
mark-indexed position. Defaults to the position. Defaults to the end of the
end of the last visual selection. last visual selection.
{bufnr} (optional, number): buffer handle or 0 {bufnr} (number|nil) buffer handle or 0 for
for current, defaults to current current, defaults to current
{offset_encoding} (string) utf-8|utf-16|utf-32|nil {offset_encoding} "utf-8"|"utf-16"|"utf-32"|nil defaults
defaults to `offset_encoding` of first to `offset_encoding` of first client of
client of `bufnr` `bufnr`
Return: ~ Return: ~
{ textDocument = { uri = `current_file_uri` }, range = { { textDocument = { uri = `current_file_uri` }, range = {
@@ -1790,8 +1795,8 @@ make_position_params({window}, {offset_encoding})
buffer and cursor position. buffer and cursor position.
Parameters: ~ Parameters: ~
{window} (optional, number): window handle or 0 {window} number|nil: window handle or 0 for
for current, defaults to current current, defaults to current
{offset_encoding} (string) utf-8|utf-16|utf-32|nil {offset_encoding} (string) utf-8|utf-16|utf-32|nil
defaults to `offset_encoding` of first defaults to `offset_encoding` of first
client of buffer of `window` client of buffer of `window`
@@ -1811,11 +1816,11 @@ make_range_params({window}, {offset_encoding})
`textDocument/rangeFormatting`. `textDocument/rangeFormatting`.
Parameters: ~ Parameters: ~
{window} (optional, number): window handle or 0 {window} number|nil: window handle or 0 for
for current, defaults to current current, defaults to current
{offset_encoding} (string) utf-8|utf-16|utf-32|nil {offset_encoding} "utf-8"|"utf-16"|"utf-32"|nil defaults
defaults to `offset_encoding` of first to `offset_encoding` of first client of
client of buffer of `window` buffer of `window`
Return: ~ Return: ~
{ textDocument = { uri = `current_file_uri` }, range = { { textDocument = { uri = `current_file_uri` }, range = {
@@ -1827,8 +1832,7 @@ make_text_document_params({bufnr})
buffer. buffer.
Parameters: ~ Parameters: ~
{bufnr} (optional, number): Buffer handle, defaults to {bufnr} number|nil: Buffer handle, defaults to current
current
Return: ~ Return: ~
`TextDocumentIdentifier` `TextDocumentIdentifier`

View File

@@ -11,8 +11,8 @@ local M = {}
--- buffer. --- buffer.
--- ---
---@param method (string) LSP method name ---@param method (string) LSP method name
---@param params (optional, table) Parameters to send to the server ---@param params (table|nil) Parameters to send to the server
---@param handler (optional, functionnil) See |lsp-handler|. Follows |lsp-handler-resolution| ---@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution|
-- --
---@returns 2-tuple: ---@returns 2-tuple:
--- - Map of client-id:request-id pairs for all successful requests. --- - Map of client-id:request-id pairs for all successful requests.
@@ -842,7 +842,7 @@ end
--- cursor position. --- cursor position.
--- ---
---@param options table|nil Optional table which holds the following optional fields: ---@param options table|nil Optional table which holds the following optional fields:
--- - context (table|nil): --- - context: (table|nil)
--- Corresponds to `CodeActionContext` of the LSP specification: --- Corresponds to `CodeActionContext` of the LSP specification:
--- - diagnostics (table|nil): --- - diagnostics (table|nil):
--- LSP `Diagnostic[]`. Inferred from the current --- LSP `Diagnostic[]`. Inferred from the current
@@ -851,11 +851,18 @@ end
--- List of LSP `CodeActionKind`s used to filter the code actions. --- List of LSP `CodeActionKind`s used to filter the code actions.
--- Most language servers support values like `refactor` --- Most language servers support values like `refactor`
--- or `quickfix`. --- or `quickfix`.
--- - filter (function|nil): --- - filter: (function|nil)
--- Predicate function taking an `CodeAction` and returning a boolean. --- Predicate taking an `CodeAction` and returning a boolean.
--- - apply (boolean|nil): --- - apply: (boolean|nil)
--- When set to `true`, and there is just one remaining action --- When set to `true`, and there is just one remaining action
--- (after filtering), the action is applied without user query. --- (after filtering), the action is applied without user query.
---
--- - range: (table|nil)
--- Range for which code actions should be requested.
--- If in visual mode this defaults to the active selection.
--- Table must contain `start` and `end` keys with {row, col} tuples
--- using mark-like indexing. See |api-indexing|
---
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
function M.code_action(options) function M.code_action(options)
validate({ options = { options, 't', true } }) validate({ options = { options, 't', true } })
@@ -870,7 +877,34 @@ function M.code_action(options)
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr) context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr)
end end
local params = util.make_range_params() local params
local mode = api.nvim_get_mode().mode
if options.range then
assert(type(options.range) == 'table', 'code_action range must be a table')
local start = assert(options.range.start, 'range must have a `start` property')
local end_ = assert(options.range['end'], 'range must have a `end` property')
params = util.make_given_range_params(start, end_)
elseif mode == 'v' or mode == 'V' then
-- [bufnum, lnum, col, off]; both row and column 1-indexed
local start = vim.fn.getpos('v')
local end_ = vim.fn.getpos('.')
local start_row = start[2]
local start_col = start[3]
local end_row = end_[2]
local end_col = end_[3]
-- A user can start visual selection at the end and move backwards
-- Normalize the range to start < end
if start_row == end_row and end_col < start_col then
end_col, start_col = start_col, end_col
elseif end_row < start_row then
start_row, end_row = end_row, start_row
start_col, end_col = end_col, start_col
end
params = util.make_given_range_params({ start_row, start_col - 1 }, { end_row, end_col - 1 })
else
params = util.make_range_params()
end
params.context = context params.context = context
code_action_request(params, options) code_action_request(params, options)
end end
@@ -891,6 +925,7 @@ end
---@param end_pos ({number, number}, optional) mark-indexed position. ---@param end_pos ({number, number}, optional) mark-indexed position.
---Defaults to the end of the last visual selection. ---Defaults to the end of the last visual selection.
function M.range_code_action(context, start_pos, end_pos) function M.range_code_action(context, start_pos, end_pos)
vim.deprecate('vim.lsp.buf.range_code_action', 'vim.lsp.buf.code_action', '0.9.0')
validate({ context = { context, 't', true } }) validate({ context = { context, 't', true } })
context = context or {} context = context or {}
if not context.diagnostics then if not context.diagnostics then

View File

@@ -1821,7 +1821,7 @@ function M.try_trim_markdown_code_blocks(lines)
end end
---@private ---@private
---@param window (optional, number): window handle or 0 for current, defaults to current ---@param window number|nil: window handle or 0 for current, defaults to current
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
local function make_position_param(window, offset_encoding) local function make_position_param(window, offset_encoding)
window = window or 0 window = window or 0
@@ -1841,7 +1841,7 @@ end
--- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position. --- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position.
--- ---
---@param window (optional, number): window handle or 0 for current, defaults to current ---@param window number|nil: window handle or 0 for current, defaults to current
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
---@returns `TextDocumentPositionParams` object ---@returns `TextDocumentPositionParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
@@ -1894,8 +1894,8 @@ end
--- `textDocument/codeAction`, `textDocument/colorPresentation`, --- `textDocument/codeAction`, `textDocument/colorPresentation`,
--- `textDocument/rangeFormatting`. --- `textDocument/rangeFormatting`.
--- ---
---@param window (optional, number): window handle or 0 for current, defaults to current ---@param window number|nil: window handle or 0 for current, defaults to current
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` ---@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of buffer of `window`
---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
---`current_position`, end = `current_position` } } ---`current_position`, end = `current_position` } }
function M.make_range_params(window, offset_encoding) function M.make_range_params(window, offset_encoding)
@@ -1911,12 +1911,12 @@ end
--- Using the given range in the current buffer, creates an object that --- Using the given range in the current buffer, creates an object that
--- is similar to |vim.lsp.util.make_range_params()|. --- is similar to |vim.lsp.util.make_range_params()|.
--- ---
---@param start_pos ({number, number}, optional) mark-indexed position. ---@param start_pos number[]|nil {row, col} mark-indexed position.
--- Defaults to the start of the last visual selection. --- Defaults to the start of the last visual selection.
---@param end_pos ({number, number}, optional) mark-indexed position. ---@param end_pos number[]|nil {row, col} mark-indexed position.
--- Defaults to the end of the last visual selection. --- Defaults to the end of the last visual selection.
---@param bufnr (optional, number): buffer handle or 0 for current, defaults to current ---@param bufnr number|nil buffer handle or 0 for current, defaults to current
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `bufnr` ---@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of `bufnr`
---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
---`start_position`, end = `end_position` } } ---`start_position`, end = `end_position` } }
function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding) function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
@@ -1956,7 +1956,7 @@ end
--- Creates a `TextDocumentIdentifier` object for the current buffer. --- Creates a `TextDocumentIdentifier` object for the current buffer.
--- ---
---@param bufnr (optional, number): Buffer handle, defaults to current ---@param bufnr number|nil: Buffer handle, defaults to current
---@returns `TextDocumentIdentifier` ---@returns `TextDocumentIdentifier`
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier
function M.make_text_document_params(bufnr) function M.make_text_document_params(bufnr)
@@ -2000,7 +2000,7 @@ end
--- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer. --- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer.
--- ---
---@param buf buffer id (0 for current) ---@param buf number buffer number (0 for current)
---@param row 0-indexed line ---@param row 0-indexed line
---@param col 0-indexed byte offset in line ---@param col 0-indexed byte offset in line
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `buf` ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `buf`