mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
LSP: Add textDocument/codeAction support (#11607)
* Add textDocument/codeAction * Add callback for workspace/executeCommand * Escape newlines in codeAction titles * Return empty list in get_line_diagnostics if no buffer diagnostics * Add stub documentation * Validate context parameter in code_action * Add support for edit in CodeAction responses * Group diagnostics by line in vim.lsp.util.get_line_diagnostics() * Advertise code action literal support
This commit is contained in:
parent
c37d9fa3da
commit
f559e5249e
@ -731,6 +731,9 @@ transform_schema_to_table()
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
Lua module: vim.lsp.buf *lsp-buf*
|
Lua module: vim.lsp.buf *lsp-buf*
|
||||||
|
|
||||||
|
code_action({context}) *vim.lsp.buf.code_action()*
|
||||||
|
TODO: Documentation
|
||||||
|
|
||||||
completion({context}) *vim.lsp.buf.completion()*
|
completion({context}) *vim.lsp.buf.completion()*
|
||||||
TODO: Documentation
|
TODO: Documentation
|
||||||
|
|
||||||
|
@ -161,5 +161,21 @@ function M.clear_references()
|
|||||||
util.buf_clear_references()
|
util.buf_clear_references()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.code_action(context)
|
||||||
|
validate { context = { context, 't', true } }
|
||||||
|
context = context or { diagnostics = util.get_line_diagnostics() }
|
||||||
|
local params = util.make_range_params()
|
||||||
|
params.context = context
|
||||||
|
request('textDocument/codeAction', params)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.execute_command(command)
|
||||||
|
validate {
|
||||||
|
command = { command.command, 's' },
|
||||||
|
arguments = { command.arguments, 't', true }
|
||||||
|
}
|
||||||
|
request('workspace/executeCommand', command)
|
||||||
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
-- vim:sw=2 ts=2 et
|
-- vim:sw=2 ts=2 et
|
||||||
|
@ -3,6 +3,7 @@ local protocol = require 'vim.lsp.protocol'
|
|||||||
local util = require 'vim.lsp.util'
|
local util = require 'vim.lsp.util'
|
||||||
local vim = vim
|
local vim = vim
|
||||||
local api = vim.api
|
local api = vim.api
|
||||||
|
local buf = require 'vim.lsp.buf'
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
@ -11,6 +12,45 @@ local function err_message(...)
|
|||||||
api.nvim_command("redraw")
|
api.nvim_command("redraw")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M['workspace/executeCommand'] = function(err, _)
|
||||||
|
if err then
|
||||||
|
error("Could not execute code action: "..err.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
M['textDocument/codeAction'] = function(_, _, actions)
|
||||||
|
if vim.tbl_isempty(actions) then
|
||||||
|
print("No code actions available")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local option_strings = {"Code Actions:"}
|
||||||
|
for i, action in ipairs(actions) do
|
||||||
|
local title = action.title:gsub('\r\n', '\\r\\n')
|
||||||
|
title = title:gsub('\n', '\\n')
|
||||||
|
table.insert(option_strings, string.format("%d. %s", i, title))
|
||||||
|
end
|
||||||
|
|
||||||
|
local choice = vim.fn.inputlist(option_strings)
|
||||||
|
if choice < 1 or choice > #actions then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local action_chosen = actions[choice]
|
||||||
|
-- textDocument/codeAction can return either Command[] or CodeAction[].
|
||||||
|
-- If it is a CodeAction, it can have either an edit, a command or both.
|
||||||
|
-- Edits should be executed first
|
||||||
|
if action_chosen.edit or type(action_chosen.command) == "table" then
|
||||||
|
if action_chosen.edit then
|
||||||
|
util.apply_workspace_edit(action_chosen.edit)
|
||||||
|
end
|
||||||
|
if type(action_chosen.command) == "table" then
|
||||||
|
buf.execute_command(action_chosen.command)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
buf.execute_command(action_chosen)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
M['workspace/applyEdit'] = function(_, _, workspace_edit)
|
M['workspace/applyEdit'] = function(_, _, workspace_edit)
|
||||||
if not workspace_edit then return end
|
if not workspace_edit then return end
|
||||||
-- TODO(ashkan) Do something more with label?
|
-- TODO(ashkan) Do something more with label?
|
||||||
|
@ -620,6 +620,15 @@ function protocol.make_client_capabilities()
|
|||||||
-- Send textDocument/didSave after saving (BufWritePost)
|
-- Send textDocument/didSave after saving (BufWritePost)
|
||||||
didSave = true;
|
didSave = true;
|
||||||
};
|
};
|
||||||
|
codeAction = {
|
||||||
|
dynamicRegistration = false;
|
||||||
|
|
||||||
|
codeActionLiteralSupport = {
|
||||||
|
codeActionKind = {
|
||||||
|
valueSet = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
completion = {
|
completion = {
|
||||||
dynamicRegistration = false;
|
dynamicRegistration = false;
|
||||||
completionItem = {
|
completionItem = {
|
||||||
|
@ -720,19 +720,28 @@ do
|
|||||||
return severity_highlights[severity]
|
return severity_highlights[severity]
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.show_line_diagnostics()
|
function M.get_line_diagnostics()
|
||||||
local bufnr = api.nvim_get_current_buf()
|
local bufnr = api.nvim_get_current_buf()
|
||||||
local line = api.nvim_win_get_cursor(0)[1] - 1
|
local linenr = api.nvim_win_get_cursor(0)[1] - 1
|
||||||
|
|
||||||
|
local buffer_diagnostics = M.diagnostics_by_buf[bufnr]
|
||||||
|
|
||||||
|
if not buffer_diagnostics then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local diagnostics_by_line = M.diagnostics_group_by_line(buffer_diagnostics)
|
||||||
|
return diagnostics_by_line[linenr] or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.show_line_diagnostics()
|
||||||
-- local marks = api.nvim_buf_get_extmarks(bufnr, diagnostic_ns, {line, 0}, {line, -1}, {})
|
-- local marks = api.nvim_buf_get_extmarks(bufnr, diagnostic_ns, {line, 0}, {line, -1}, {})
|
||||||
-- if #marks == 0 then
|
-- if #marks == 0 then
|
||||||
-- return
|
-- return
|
||||||
-- end
|
-- end
|
||||||
local lines = {"Diagnostics:"}
|
local lines = {"Diagnostics:"}
|
||||||
local highlights = {{0, "Bold"}}
|
local highlights = {{0, "Bold"}}
|
||||||
|
local line_diagnostics = M.get_line_diagnostics()
|
||||||
local buffer_diagnostics = M.diagnostics_by_buf[bufnr]
|
|
||||||
if not buffer_diagnostics then return end
|
|
||||||
local line_diagnostics = M.diagnostics_group_by_line(buffer_diagnostics)[line]
|
|
||||||
if not line_diagnostics then return end
|
if not line_diagnostics then return end
|
||||||
|
|
||||||
for i, diagnostic in ipairs(line_diagnostics) do
|
for i, diagnostic in ipairs(line_diagnostics) do
|
||||||
@ -1044,14 +1053,26 @@ function M.try_trim_markdown_code_blocks(lines)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local str_utfindex = vim.str_utfindex
|
local str_utfindex = vim.str_utfindex
|
||||||
function M.make_position_params()
|
local function make_position_param()
|
||||||
local row, col = unpack(api.nvim_win_get_cursor(0))
|
local row, col = unpack(api.nvim_win_get_cursor(0))
|
||||||
row = row - 1
|
row = row - 1
|
||||||
local line = api.nvim_buf_get_lines(0, row, row+1, true)[1]
|
local line = api.nvim_buf_get_lines(0, row, row+1, true)[1]
|
||||||
col = str_utfindex(line, col)
|
col = str_utfindex(line, col)
|
||||||
|
return { line = row; character = col; }
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.make_position_params()
|
||||||
return {
|
return {
|
||||||
textDocument = M.make_text_document_params();
|
textDocument = M.make_text_document_params();
|
||||||
position = { line = row; character = col; }
|
position = make_position_param()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.make_range_params()
|
||||||
|
local position = make_position_param()
|
||||||
|
return {
|
||||||
|
textDocument = { uri = vim.uri_from_bufnr(0) },
|
||||||
|
range = { start = position; ["end"] = position; }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user