aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin
diff options
context:
space:
mode:
authorRiley Bruins <ribru17@hotmail.com>2025-08-31 14:09:12 -0700
committerGitHub <noreply@github.com>2025-08-31 14:09:12 -0700
commit77e3efecee4e9948044ec02caeaf6fec496c6c02 (patch)
tree714d77ad67ee34d796f4fb33ceba65da52cc4a83 /test/functional/plugin
parentf311c96973a561ba5e664f46e758a97fd10acdcb (diff)
downloadrneovim-77e3efecee4e9948044ec02caeaf6fec496c6c02.tar.gz
rneovim-77e3efecee4e9948044ec02caeaf6fec496c6c02.tar.bz2
rneovim-77e3efecee4e9948044ec02caeaf6fec496c6c02.zip
feat(lsp): support `textDocument/onTypeFormatting` (#34637)
Implements [on-type formatting](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_onTypeFormatting) using a `vim.on_key()` approach to listen to typed keys. It will listen to keys on the *left hand side* of mappings. The `on_key` callback is cleared when detaching the last on-type formatting client. This feature is disabled by default. Co-authored-by: Maria José Solano <majosolano99@gmail.com>
Diffstat (limited to 'test/functional/plugin')
-rw-r--r--test/functional/plugin/lsp/on_type_formatting_spec.lua174
1 files changed, 174 insertions, 0 deletions
diff --git a/test/functional/plugin/lsp/on_type_formatting_spec.lua b/test/functional/plugin/lsp/on_type_formatting_spec.lua
new file mode 100644
index 0000000000..211350335e
--- /dev/null
+++ b/test/functional/plugin/lsp/on_type_formatting_spec.lua
@@ -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)