mirror of
https://github.com/neovim/neovim.git
synced 2025-09-03 18:08:16 +00:00
Compare commits
5 Commits
b4a609e158
...
38073747ae
Author | SHA1 | Date | |
---|---|---|---|
![]() |
38073747ae | ||
![]() |
c6bfc203f1 | ||
![]() |
77e3efecee | ||
![]() |
f311c96973 | ||
![]() |
582e0714b5 |
@@ -2377,6 +2377,33 @@ set_level({level}) *vim.lsp.log.set_level()*
|
||||
• {level} (`string|integer`) One of |vim.log.levels|
|
||||
|
||||
|
||||
==============================================================================
|
||||
Lua module: vim.lsp.on_type_formatting *lsp-on_type_formatting*
|
||||
|
||||
enable({enable}, {filter}) *vim.lsp.on_type_formatting.enable()*
|
||||
Enables/disables on-type formatting globally or for the {filter}ed scope.
|
||||
The following are some practical usage examples: >lua
|
||||
-- Enable for all clients
|
||||
vim.lsp.on_type_formatting.enable()
|
||||
|
||||
-- Enable for a specific client
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(args)
|
||||
local client_id = args.data.client_id
|
||||
local client = assert(vim.lsp.get_client_by_id(client_id))
|
||||
if client.name == 'rust-analyzer' then
|
||||
vim.lsp.on_type_formatting.enable(true, { client_id = client_id })
|
||||
end
|
||||
end,
|
||||
})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {enable} (`boolean?`) true/nil to enable, false to disable.
|
||||
• {filter} (`table?`) Optional filters |kwargs|:
|
||||
• {client_id} (`integer?`) Client ID, or `nil` for all.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Lua module: vim.lsp.rpc *lsp-rpc*
|
||||
|
||||
|
@@ -242,6 +242,8 @@ LSP
|
||||
• |vim.lsp.buf.signature_help()| supports "noActiveParameterSupport".
|
||||
• Support for `textDocument/inlineCompletion` |lsp-inline_completion|
|
||||
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_inlineCompletion
|
||||
• Support for `textDocument/onTypeFormatting`: |lsp-on_type_formatting|
|
||||
https://microsoft.github.io/language-server-protocol/specification/#textDocument_onTypeFormatting
|
||||
|
||||
LUA
|
||||
|
||||
|
@@ -19,6 +19,7 @@ local lsp = vim._defer_require('vim.lsp', {
|
||||
inline_completion = ..., --- @module 'vim.lsp.inline_completion'
|
||||
linked_editing_range = ..., --- @module 'vim.lsp.linked_editing_range'
|
||||
log = ..., --- @module 'vim.lsp.log'
|
||||
on_type_formatting = ..., --- @module 'vim.lsp.on_type_formatting'
|
||||
protocol = ..., --- @module 'vim.lsp.protocol'
|
||||
rpc = ..., --- @module 'vim.lsp.rpc'
|
||||
semantic_tokens = ..., --- @module 'vim.lsp.semantic_tokens'
|
||||
|
@@ -211,6 +211,9 @@ local all_clients = {}
|
||||
---
|
||||
--- @field _enabled_capabilities table<vim.lsp.capability.Name, boolean?>
|
||||
---
|
||||
--- Whether on-type formatting is enabled for this client.
|
||||
--- @field _otf_enabled boolean?
|
||||
---
|
||||
--- Track this so that we can escalate automatically if we've already tried a
|
||||
--- graceful shutdown
|
||||
--- @field private _graceful_shutdown_failed true?
|
||||
|
261
runtime/lua/vim/lsp/on_type_formatting.lua
Normal file
261
runtime/lua/vim/lsp/on_type_formatting.lua
Normal file
@@ -0,0 +1,261 @@
|
||||
local api = vim.api
|
||||
local lsp = vim.lsp
|
||||
local util = lsp.util
|
||||
local method = lsp.protocol.Methods.textDocument_onTypeFormatting
|
||||
|
||||
local schedule = vim.schedule
|
||||
local current_buf = api.nvim_get_current_buf
|
||||
local get_mode = api.nvim_get_mode
|
||||
|
||||
local ns = api.nvim_create_namespace('nvim.lsp.on_type_formatting')
|
||||
local augroup = api.nvim_create_augroup('nvim.lsp.on_type_formatting', {})
|
||||
|
||||
local M = {}
|
||||
|
||||
--- @alias vim.lsp.on_type_formatting.BufTriggers table<string, table<integer, vim.lsp.Client>>
|
||||
|
||||
--- A map from bufnr -> trigger character -> client ID -> client
|
||||
--- @type table<integer, vim.lsp.on_type_formatting.BufTriggers>
|
||||
local buf_handles = {}
|
||||
|
||||
--- |lsp-handler| for the `textDocument/onTypeFormatting` method.
|
||||
---
|
||||
--- @param err? lsp.ResponseError
|
||||
--- @param result? lsp.TextEdit[]
|
||||
--- @param ctx lsp.HandlerContext
|
||||
local function on_type_formatting(err, result, ctx)
|
||||
if err then
|
||||
lsp.log.error('on_type_formatting', err)
|
||||
return
|
||||
end
|
||||
|
||||
local bufnr = assert(ctx.bufnr)
|
||||
|
||||
-- A `null` result is equivalent to an empty `TextEdit[]` result; no work should be done.
|
||||
if not result or not api.nvim_buf_is_loaded(bufnr) or util.buf_versions[bufnr] ~= ctx.version then
|
||||
return
|
||||
end
|
||||
|
||||
local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
|
||||
|
||||
util.apply_text_edits(result, ctx.bufnr, client.offset_encoding)
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param typed string
|
||||
---@param triggered_clients vim.lsp.Client[]
|
||||
---@param idx integer?
|
||||
---@param client vim.lsp.Client?
|
||||
local function format_iter(bufnr, typed, triggered_clients, idx, client)
|
||||
if not idx or not client then
|
||||
return
|
||||
end
|
||||
---@type lsp.DocumentOnTypeFormattingParams
|
||||
local params = vim.tbl_extend(
|
||||
'keep',
|
||||
util.make_formatting_params(),
|
||||
util.make_position_params(0, client.offset_encoding),
|
||||
{ ch = typed }
|
||||
)
|
||||
client:request(method, params, function(...)
|
||||
on_type_formatting(...)
|
||||
format_iter(bufnr, typed, triggered_clients, next(triggered_clients, idx))
|
||||
end, bufnr)
|
||||
end
|
||||
|
||||
---@param typed string
|
||||
local function on_key(_, typed)
|
||||
local mode = get_mode()
|
||||
if mode.blocking or mode.mode ~= 'i' then
|
||||
return
|
||||
end
|
||||
|
||||
local bufnr = current_buf()
|
||||
|
||||
local buf_handle = buf_handles[bufnr]
|
||||
if not buf_handle then
|
||||
return
|
||||
end
|
||||
|
||||
-- LSP expects '\n' for formatting on newline
|
||||
if typed == '\r' then
|
||||
typed = '\n'
|
||||
end
|
||||
|
||||
local triggered_clients = buf_handle[typed]
|
||||
if not triggered_clients then
|
||||
return
|
||||
end
|
||||
|
||||
-- Schedule the formatting to occur *after* the LSP is aware of the inserted character
|
||||
schedule(function()
|
||||
format_iter(bufnr, typed, triggered_clients, next(triggered_clients))
|
||||
end)
|
||||
end
|
||||
|
||||
--- @param client vim.lsp.Client
|
||||
--- @param bufnr integer
|
||||
local function detach(client, bufnr)
|
||||
local buf_handle = buf_handles[bufnr]
|
||||
if not buf_handle then
|
||||
return
|
||||
end
|
||||
|
||||
local client_id = client.id
|
||||
|
||||
-- Remove this client from its associated trigger characters
|
||||
for trigger_char, attached_clients in pairs(buf_handle) do
|
||||
attached_clients[client_id] = nil
|
||||
|
||||
-- Remove the trigger character if we detached its last client.
|
||||
if not next(attached_clients) then
|
||||
buf_handle[trigger_char] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove the buf handle and its autocmds if we removed its last client.
|
||||
if not next(buf_handle) then
|
||||
buf_handles[bufnr] = nil
|
||||
api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
|
||||
|
||||
-- Remove the on_key callback if we removed the last buf handle.
|
||||
if not next(buf_handles) then
|
||||
vim.on_key(nil, ns)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param client vim.lsp.Client
|
||||
--- @param bufnr integer
|
||||
local function attach(client, bufnr)
|
||||
if not client:supports_method(method, bufnr) then
|
||||
return
|
||||
end
|
||||
|
||||
local client_id = client.id
|
||||
---@type lsp.DocumentOnTypeFormattingOptions
|
||||
local otf_capabilities =
|
||||
assert(vim.tbl_get(client.server_capabilities, 'documentOnTypeFormattingProvider'))
|
||||
|
||||
-- Set on_key callback, clearing first in case it was already registered.
|
||||
vim.on_key(nil, ns)
|
||||
vim.on_key(on_key, ns)
|
||||
|
||||
-- Populate the buf handle data. We cannot use defaulttable here because then an empty table will
|
||||
-- be created for each unique keystroke
|
||||
local buf_handle = buf_handles[bufnr] or {}
|
||||
buf_handles[bufnr] = buf_handle
|
||||
|
||||
local trigger = buf_handle[otf_capabilities.firstTriggerCharacter] or {}
|
||||
buf_handle[otf_capabilities.firstTriggerCharacter] = trigger
|
||||
trigger[client_id] = client
|
||||
|
||||
for _, char in ipairs(otf_capabilities.moreTriggerCharacter or {}) do
|
||||
trigger = buf_handle[char] or {}
|
||||
buf_handle[char] = trigger
|
||||
trigger[client_id] = client
|
||||
end
|
||||
|
||||
api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
|
||||
api.nvim_create_autocmd('LspDetach', {
|
||||
buffer = bufnr,
|
||||
desc = 'Detach on-type formatting module when the client detaches',
|
||||
group = augroup,
|
||||
callback = function(args)
|
||||
local detached_client = assert(lsp.get_client_by_id(args.data.client_id))
|
||||
detach(detached_client, bufnr)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
desc = 'Enable on-type formatting for all buffers with individually-enabled clients.',
|
||||
callback = function(ev)
|
||||
local buf = ev.buf
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client._otf_enabled then
|
||||
attach(client, buf)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
---@param enable boolean
|
||||
---@param client vim.lsp.Client
|
||||
local function toggle_for_client(enable, client)
|
||||
local handler = enable and attach or detach
|
||||
|
||||
-- Toggle for buffers already attached.
|
||||
for bufnr, _ in pairs(client.attached_buffers) do
|
||||
handler(client, bufnr)
|
||||
end
|
||||
|
||||
client._otf_enabled = enable
|
||||
end
|
||||
|
||||
---@param enable boolean
|
||||
local function toggle_globally(enable)
|
||||
-- Toggle for clients that have already attached.
|
||||
local clients = lsp.get_clients({ method = method })
|
||||
for _, client in ipairs(clients) do
|
||||
toggle_for_client(enable, client)
|
||||
end
|
||||
|
||||
-- If disabling, only clear the attachment autocmd. If enabling, create it as well.
|
||||
local group = api.nvim_create_augroup('nvim.lsp.on_type_formatting', { clear = true })
|
||||
if enable then
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
group = group,
|
||||
desc = 'Enable on-type formatting for ALL clients by default.',
|
||||
callback = function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client._otf_enabled ~= false then
|
||||
attach(client, ev.buf)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--- Optional filters |kwargs|:
|
||||
--- @inlinedoc
|
||||
--- @class vim.lsp.on_type_formatting.enable.Filter
|
||||
--- @field client_id integer? Client ID, or `nil` for all.
|
||||
|
||||
--- Enables/disables on-type formatting globally or for the {filter}ed scope. The following are some
|
||||
--- practical usage examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- Enable for all clients
|
||||
--- vim.lsp.on_type_formatting.enable()
|
||||
---
|
||||
--- -- Enable for a specific client
|
||||
--- vim.api.nvim_create_autocmd('LspAttach', {
|
||||
--- callback = function(args)
|
||||
--- local client_id = args.data.client_id
|
||||
--- local client = assert(vim.lsp.get_client_by_id(client_id))
|
||||
--- if client.name == 'rust-analyzer' then
|
||||
--- vim.lsp.on_type_formatting.enable(true, { client_id = client_id })
|
||||
--- end
|
||||
--- end,
|
||||
--- })
|
||||
--- ```
|
||||
---
|
||||
--- @param enable? boolean true/nil to enable, false to disable.
|
||||
--- @param filter vim.lsp.on_type_formatting.enable.Filter?
|
||||
function M.enable(enable, filter)
|
||||
vim.validate('enable', enable, 'boolean', true)
|
||||
vim.validate('filter', filter, 'table', true)
|
||||
|
||||
enable = enable ~= false
|
||||
filter = filter or {}
|
||||
|
||||
if filter.client_id then
|
||||
local client =
|
||||
assert(lsp.get_client_by_id(filter.client_id), 'Client not found for id ' .. filter.client_id)
|
||||
toggle_for_client(enable, client)
|
||||
else
|
||||
toggle_globally(enable)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
@@ -572,6 +572,9 @@ function protocol.make_client_capabilities()
|
||||
linkedEditingRange = {
|
||||
dynamicRegistration = false,
|
||||
},
|
||||
onTypeFormatting = {
|
||||
dynamicRegistration = false,
|
||||
},
|
||||
},
|
||||
workspace = {
|
||||
symbol = {
|
||||
|
@@ -732,10 +732,9 @@ local function python()
|
||||
local message = 'Detected pip upgrade failure: Python executable can import "pynvim" but not "neovim": '
|
||||
.. pynvim_exe
|
||||
local advice = {
|
||||
'Use that Python version to reinstall "pynvim" and optionally "neovim".',
|
||||
'Use that Python version to uninstall any "pynvim" or "neovim", e.g.:',
|
||||
pynvim_exe .. ' -m pip uninstall pynvim neovim',
|
||||
pynvim_exe .. ' -m pip install pynvim',
|
||||
pynvim_exe .. ' -m pip install neovim # only if needed by third-party software',
|
||||
'Then see :help provider-python for "pynvim" installation steps.',
|
||||
}
|
||||
health.error(message, advice)
|
||||
end
|
||||
@@ -761,7 +760,7 @@ local function python()
|
||||
if is_bad_response(current) then
|
||||
health.error(
|
||||
'pynvim is not installed.\nError: ' .. current,
|
||||
'Run in shell: ' .. python_exe .. ' -m pip install pynvim'
|
||||
'See :help provider-python for "pynvim" installation steps.'
|
||||
)
|
||||
end
|
||||
|
||||
|
@@ -286,6 +286,7 @@ local config = {
|
||||
'inline_completion.lua',
|
||||
'linked_editing_range.lua',
|
||||
'log.lua',
|
||||
'on_type_formatting.lua',
|
||||
'rpc.lua',
|
||||
'semantic_tokens.lua',
|
||||
'tagfunc.lua',
|
||||
|
@@ -317,7 +317,7 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
// Use specified size.
|
||||
minitems = MAX(minitems, ht->ht_used);
|
||||
// array is up to 2/3 full
|
||||
minsize = minitems * 3 / 2;
|
||||
minsize = (minitems * 3 + 1) / 2;
|
||||
}
|
||||
|
||||
size_t newsize = HT_INIT_SIZE;
|
||||
|
@@ -61,7 +61,7 @@ static const int included_patches[] = {
|
||||
2423,
|
||||
2422,
|
||||
2421,
|
||||
// 2420,
|
||||
2420,
|
||||
2419,
|
||||
// 2418,
|
||||
2417,
|
||||
@@ -110,7 +110,7 @@ static const int included_patches[] = {
|
||||
2374,
|
||||
2373,
|
||||
2372,
|
||||
// 2371,
|
||||
2371,
|
||||
2370,
|
||||
2369,
|
||||
2368,
|
||||
@@ -147,7 +147,7 @@ static const int included_patches[] = {
|
||||
2337,
|
||||
2336,
|
||||
2335,
|
||||
// 2334,
|
||||
2334,
|
||||
2333,
|
||||
2332,
|
||||
2331,
|
||||
@@ -174,14 +174,14 @@ static const int included_patches[] = {
|
||||
2310,
|
||||
2309,
|
||||
2308,
|
||||
// 2307,
|
||||
2307,
|
||||
2306,
|
||||
2305,
|
||||
2304,
|
||||
2303,
|
||||
2302,
|
||||
2301,
|
||||
// 2300,
|
||||
2300,
|
||||
2299,
|
||||
2298,
|
||||
2297,
|
||||
@@ -193,9 +193,9 @@ static const int included_patches[] = {
|
||||
2291,
|
||||
2290,
|
||||
2289,
|
||||
// 2288,
|
||||
// 2287,
|
||||
// 2286,
|
||||
2288,
|
||||
2287,
|
||||
2286,
|
||||
2285,
|
||||
2284,
|
||||
2283,
|
||||
@@ -204,7 +204,7 @@ static const int included_patches[] = {
|
||||
2280,
|
||||
// 2279,
|
||||
2278,
|
||||
// 2277,
|
||||
2277,
|
||||
2276,
|
||||
2275,
|
||||
2274,
|
||||
@@ -241,7 +241,7 @@ static const int included_patches[] = {
|
||||
2243,
|
||||
2242,
|
||||
// 2241,
|
||||
// 2240,
|
||||
2240,
|
||||
2239,
|
||||
2238,
|
||||
2237,
|
||||
@@ -268,10 +268,10 @@ static const int included_patches[] = {
|
||||
2216,
|
||||
2215,
|
||||
2214,
|
||||
// 2213,
|
||||
2213,
|
||||
2212,
|
||||
2211,
|
||||
// 2210,
|
||||
2210,
|
||||
2209,
|
||||
// 2208,
|
||||
2207,
|
||||
@@ -317,7 +317,7 @@ static const int included_patches[] = {
|
||||
2167,
|
||||
2166,
|
||||
2165,
|
||||
// 2164,
|
||||
2164,
|
||||
2163,
|
||||
2162,
|
||||
2161,
|
||||
@@ -367,12 +367,12 @@ static const int included_patches[] = {
|
||||
2117,
|
||||
2116,
|
||||
2115,
|
||||
// 2114,
|
||||
2114,
|
||||
2113,
|
||||
2112,
|
||||
2111,
|
||||
// 2110,
|
||||
// 2109,
|
||||
2110,
|
||||
2109,
|
||||
2108,
|
||||
2107,
|
||||
2106,
|
||||
@@ -449,7 +449,7 @@ static const int included_patches[] = {
|
||||
2035,
|
||||
2034,
|
||||
2033,
|
||||
// 2032,
|
||||
2032,
|
||||
2031,
|
||||
2030,
|
||||
2029,
|
||||
@@ -472,7 +472,7 @@ static const int included_patches[] = {
|
||||
2012,
|
||||
2011,
|
||||
2010,
|
||||
// 2009,
|
||||
2009,
|
||||
2008,
|
||||
2007,
|
||||
2006,
|
||||
@@ -483,8 +483,8 @@ static const int included_patches[] = {
|
||||
2001,
|
||||
2000,
|
||||
// 1999,
|
||||
// 1998,
|
||||
// 1997,
|
||||
1998,
|
||||
1997,
|
||||
// 1996,
|
||||
1995,
|
||||
1994,
|
||||
@@ -518,11 +518,11 @@ static const int included_patches[] = {
|
||||
1966,
|
||||
1965,
|
||||
// 1964,
|
||||
// 1963,
|
||||
1963,
|
||||
1962,
|
||||
1961,
|
||||
1960,
|
||||
// 1959,
|
||||
1959,
|
||||
1958,
|
||||
// 1957,
|
||||
1956,
|
||||
@@ -536,7 +536,7 @@ static const int included_patches[] = {
|
||||
1948,
|
||||
1947,
|
||||
1946,
|
||||
// 1945,
|
||||
1945,
|
||||
// 1944,
|
||||
// 1943,
|
||||
1942,
|
||||
@@ -545,14 +545,14 @@ static const int included_patches[] = {
|
||||
// 1939,
|
||||
1938,
|
||||
1937,
|
||||
// 1936,
|
||||
1936,
|
||||
1935,
|
||||
// 1934,
|
||||
1934,
|
||||
1933,
|
||||
1932,
|
||||
1931,
|
||||
1930,
|
||||
// 1929,
|
||||
1929,
|
||||
// 1928,
|
||||
1927,
|
||||
1926,
|
||||
@@ -563,8 +563,8 @@ static const int included_patches[] = {
|
||||
1921,
|
||||
// 1920,
|
||||
// 1919,
|
||||
// 1918,
|
||||
// 1917,
|
||||
1918,
|
||||
1917,
|
||||
1916,
|
||||
1915,
|
||||
1914,
|
||||
@@ -574,12 +574,12 @@ static const int included_patches[] = {
|
||||
1910,
|
||||
1909,
|
||||
// 1908,
|
||||
// 1907,
|
||||
1907,
|
||||
// 1906,
|
||||
// 1905,
|
||||
// 1904,
|
||||
1903,
|
||||
// 1902,
|
||||
1902,
|
||||
1901,
|
||||
1900,
|
||||
1899,
|
||||
@@ -607,7 +607,7 @@ static const int included_patches[] = {
|
||||
1877,
|
||||
1876,
|
||||
1875,
|
||||
// 1874,
|
||||
1874,
|
||||
1873,
|
||||
1872,
|
||||
1871,
|
||||
@@ -631,12 +631,12 @@ static const int included_patches[] = {
|
||||
1853,
|
||||
1852,
|
||||
// 1851,
|
||||
// 1850,
|
||||
1850,
|
||||
1849,
|
||||
1848,
|
||||
1847,
|
||||
1846,
|
||||
// 1845,
|
||||
1845,
|
||||
1844,
|
||||
1843,
|
||||
1842,
|
||||
@@ -667,7 +667,7 @@ static const int included_patches[] = {
|
||||
1817,
|
||||
1816,
|
||||
1815,
|
||||
// 1814,
|
||||
1814,
|
||||
// 1813,
|
||||
1812,
|
||||
// 1811,
|
||||
@@ -692,28 +692,28 @@ static const int included_patches[] = {
|
||||
1792,
|
||||
1791,
|
||||
1790,
|
||||
// 1789,
|
||||
1789,
|
||||
1788,
|
||||
// 1787,
|
||||
// 1786,
|
||||
1786,
|
||||
1785,
|
||||
// 1784,
|
||||
1783,
|
||||
1782,
|
||||
1781,
|
||||
1780,
|
||||
// 1779,
|
||||
// 1778,
|
||||
1779,
|
||||
1778,
|
||||
1777,
|
||||
1776,
|
||||
1775,
|
||||
1774,
|
||||
// 1773,
|
||||
1773,
|
||||
1772,
|
||||
1771,
|
||||
// 1770,
|
||||
1769,
|
||||
// 1768,
|
||||
1768,
|
||||
1767,
|
||||
1766,
|
||||
1765,
|
||||
@@ -726,10 +726,10 @@ static const int included_patches[] = {
|
||||
1758,
|
||||
1757,
|
||||
1756,
|
||||
// 1755,
|
||||
// 1754,
|
||||
// 1753,
|
||||
// 1752,
|
||||
1755,
|
||||
1754,
|
||||
1753,
|
||||
1752,
|
||||
// 1751,
|
||||
1750,
|
||||
1749,
|
||||
@@ -748,7 +748,7 @@ static const int included_patches[] = {
|
||||
1736,
|
||||
1735,
|
||||
1734,
|
||||
// 1733,
|
||||
1733,
|
||||
1732,
|
||||
1731,
|
||||
1730,
|
||||
@@ -762,7 +762,7 @@ static const int included_patches[] = {
|
||||
1722,
|
||||
1721,
|
||||
1720,
|
||||
// 1719,
|
||||
1719,
|
||||
// 1718,
|
||||
1717,
|
||||
1716,
|
||||
@@ -772,9 +772,9 @@ static const int included_patches[] = {
|
||||
1712,
|
||||
1711,
|
||||
1710,
|
||||
// 1709,
|
||||
1709,
|
||||
1708,
|
||||
// 1707,
|
||||
1707,
|
||||
1706,
|
||||
1705,
|
||||
1704,
|
||||
@@ -803,9 +803,9 @@ static const int included_patches[] = {
|
||||
1681,
|
||||
1680,
|
||||
1679,
|
||||
// 1678,
|
||||
1678,
|
||||
1677,
|
||||
// 1676,
|
||||
1676,
|
||||
1675,
|
||||
1674,
|
||||
// 1673,
|
||||
@@ -815,8 +815,8 @@ static const int included_patches[] = {
|
||||
1669,
|
||||
1668,
|
||||
1667,
|
||||
// 1666,
|
||||
// 1665,
|
||||
1666,
|
||||
1665,
|
||||
1664,
|
||||
1663,
|
||||
1662,
|
||||
@@ -825,17 +825,17 @@ static const int included_patches[] = {
|
||||
// 1659,
|
||||
1658,
|
||||
1657,
|
||||
// 1656,
|
||||
1656,
|
||||
1655,
|
||||
1654,
|
||||
1653,
|
||||
1652,
|
||||
1651,
|
||||
1650,
|
||||
// 1649,
|
||||
1649,
|
||||
1648,
|
||||
1647,
|
||||
// 1646,
|
||||
1646,
|
||||
1645,
|
||||
1644,
|
||||
1643,
|
||||
@@ -845,7 +845,7 @@ static const int included_patches[] = {
|
||||
1639,
|
||||
1638,
|
||||
1637,
|
||||
// 1636,
|
||||
1636,
|
||||
1635,
|
||||
1634,
|
||||
1633,
|
||||
@@ -859,14 +859,14 @@ static const int included_patches[] = {
|
||||
1625,
|
||||
1624,
|
||||
1623,
|
||||
// 1622,
|
||||
1622,
|
||||
1621,
|
||||
// 1620,
|
||||
1620,
|
||||
1619,
|
||||
1618,
|
||||
// 1617,
|
||||
1617,
|
||||
1616,
|
||||
// 1615,
|
||||
1615,
|
||||
1614,
|
||||
1613,
|
||||
// 1612,
|
||||
@@ -879,13 +879,13 @@ static const int included_patches[] = {
|
||||
1605,
|
||||
1604,
|
||||
1603,
|
||||
// 1602,
|
||||
1602,
|
||||
1601,
|
||||
// 1600,
|
||||
1599,
|
||||
1598,
|
||||
// 1597,
|
||||
// 1596,
|
||||
1596,
|
||||
1595,
|
||||
1594,
|
||||
1593,
|
||||
@@ -919,7 +919,7 @@ static const int included_patches[] = {
|
||||
1565,
|
||||
1564,
|
||||
1563,
|
||||
// 1562,
|
||||
1562,
|
||||
// 1561,
|
||||
// 1560,
|
||||
// 1559,
|
||||
@@ -931,7 +931,7 @@ static const int included_patches[] = {
|
||||
// 1553,
|
||||
1552,
|
||||
1551,
|
||||
// 1550,
|
||||
1550,
|
||||
1549,
|
||||
// 1548,
|
||||
1547,
|
||||
@@ -954,7 +954,7 @@ static const int included_patches[] = {
|
||||
1530,
|
||||
1529,
|
||||
1528,
|
||||
// 1527,
|
||||
1527,
|
||||
1526,
|
||||
// 1525,
|
||||
1524,
|
||||
@@ -1222,7 +1222,7 @@ static const int included_patches[] = {
|
||||
1262,
|
||||
1261,
|
||||
1260,
|
||||
// 1259,
|
||||
1259,
|
||||
1258,
|
||||
1257,
|
||||
1256,
|
||||
@@ -1345,7 +1345,7 @@ static const int included_patches[] = {
|
||||
1139,
|
||||
1138,
|
||||
1137,
|
||||
// 1136,
|
||||
1136,
|
||||
1135,
|
||||
1134,
|
||||
1133,
|
||||
@@ -1398,7 +1398,7 @@ static const int included_patches[] = {
|
||||
1086,
|
||||
1085,
|
||||
1084,
|
||||
// 1083,
|
||||
1083,
|
||||
1082,
|
||||
1081,
|
||||
1080,
|
||||
|
174
test/functional/plugin/lsp/on_type_formatting_spec.lua
Normal file
174
test/functional/plugin/lsp/on_type_formatting_spec.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
local t = require('test.testutil')
|
||||
local n = require('test.functional.testnvim')()
|
||||
local t_lsp = require('test.functional.plugin.lsp.testutil')
|
||||
local retry = t.retry
|
||||
|
||||
local eq = t.eq
|
||||
local dedent = t.dedent
|
||||
local exec_lua = n.exec_lua
|
||||
local insert = n.insert
|
||||
local feed = n.feed
|
||||
|
||||
local clear_notrace = t_lsp.clear_notrace
|
||||
local create_server_definition = t_lsp.create_server_definition
|
||||
|
||||
describe('vim.lsp.on_type_formatting', function()
|
||||
local text = dedent([[
|
||||
int main() {
|
||||
int hi
|
||||
}]])
|
||||
|
||||
before_each(function()
|
||||
clear_notrace()
|
||||
|
||||
exec_lua(create_server_definition)
|
||||
exec_lua(function()
|
||||
_G.server = _G._create_server({
|
||||
capabilities = {
|
||||
documentOnTypeFormattingProvider = {
|
||||
firstTriggerCharacter = '=',
|
||||
},
|
||||
},
|
||||
handlers = {
|
||||
---@param params lsp.DocumentOnTypeFormattingParams
|
||||
---@param callback fun(err?: lsp.ResponseError, result?: lsp.TextEdit[])
|
||||
['textDocument/onTypeFormatting'] = function(_, params, callback)
|
||||
callback(nil, {
|
||||
{
|
||||
newText = ';',
|
||||
range = {
|
||||
start = params.position,
|
||||
['end'] = params.position,
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
},
|
||||
})
|
||||
|
||||
_G.server_id = vim.lsp.start({
|
||||
name = 'dummy',
|
||||
cmd = _G.server.cmd,
|
||||
})
|
||||
vim.lsp.on_type_formatting.enable(true, { client_id = _G.server_id })
|
||||
end)
|
||||
|
||||
insert(text)
|
||||
end)
|
||||
|
||||
it('enables formatting on type', function()
|
||||
exec_lua(function()
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_win_set_cursor(win, { 2, 0 })
|
||||
end)
|
||||
feed('A = 5')
|
||||
retry(nil, 100, function()
|
||||
eq(
|
||||
{
|
||||
'int main() {',
|
||||
' int hi = 5;',
|
||||
'}',
|
||||
},
|
||||
exec_lua(function()
|
||||
return vim.api.nvim_buf_get_lines(0, 0, -1, false)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('works with multiple clients', function()
|
||||
exec_lua(function()
|
||||
vim.lsp.on_type_formatting.enable(true)
|
||||
_G.server2 = _G._create_server({
|
||||
capabilities = {
|
||||
documentOnTypeFormattingProvider = {
|
||||
firstTriggerCharacter = '.',
|
||||
moreTriggerCharacter = { '=' },
|
||||
},
|
||||
},
|
||||
handlers = {
|
||||
---@param params lsp.DocumentOnTypeFormattingParams
|
||||
---@param callback fun(err?: lsp.ResponseError, result?: lsp.TextEdit[])
|
||||
['textDocument/onTypeFormatting'] = function(_, params, callback)
|
||||
callback(nil, {
|
||||
{
|
||||
newText = ';',
|
||||
range = {
|
||||
start = params.position,
|
||||
['end'] = params.position,
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
},
|
||||
})
|
||||
|
||||
vim.lsp.start({
|
||||
name = 'dummy2',
|
||||
cmd = _G.server2.cmd,
|
||||
})
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_win_set_cursor(win, { 2, 0 })
|
||||
end)
|
||||
feed('A =')
|
||||
retry(nil, 100, function()
|
||||
eq(
|
||||
{
|
||||
'int main() {',
|
||||
' int hi =;;',
|
||||
'}',
|
||||
},
|
||||
exec_lua(function()
|
||||
return vim.api.nvim_buf_get_lines(0, 0, -1, false)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('can be disabled', function()
|
||||
exec_lua(function()
|
||||
vim.lsp.on_type_formatting.enable(false, { client_id = _G.server_id })
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_win_set_cursor(win, { 2, 0 })
|
||||
end)
|
||||
feed('A = 5')
|
||||
eq(
|
||||
{
|
||||
'int main() {',
|
||||
' int hi = 5',
|
||||
'}',
|
||||
},
|
||||
exec_lua(function()
|
||||
return vim.api.nvim_buf_get_lines(0, 0, -1, false)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
it('attaches to new buffers', function()
|
||||
exec_lua(function()
|
||||
local buf = vim.api.nvim_create_buf(true, false)
|
||||
vim.api.nvim_set_current_buf(buf)
|
||||
vim.api.nvim_buf_set_lines(buf, 0, -1, false, {
|
||||
'int main() {',
|
||||
' int hi',
|
||||
'}',
|
||||
})
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_win_set_cursor(win, { 2, 0 })
|
||||
vim.lsp.buf_attach_client(buf, _G.server_id)
|
||||
end)
|
||||
feed('A = 5')
|
||||
retry(nil, 100, function()
|
||||
eq(
|
||||
{
|
||||
'int main() {',
|
||||
' int hi = 5;',
|
||||
'}',
|
||||
},
|
||||
exec_lua(function()
|
||||
return vim.api.nvim_buf_get_lines(0, 0, -1, false)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
end)
|
Reference in New Issue
Block a user