aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/plugin/lsp')
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua54
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua61
-rw-r--r--test/functional/plugin/lsp/folding_range_spec.lua647
-rw-r--r--test/functional/plugin/lsp/handler_spec.lua42
-rw-r--r--test/functional/plugin/lsp/incremental_sync_spec.lua10
-rw-r--r--test/functional/plugin/lsp/semantic_tokens_spec.lua2
-rw-r--r--test/functional/plugin/lsp/testutil.lua13
-rw-r--r--test/functional/plugin/lsp/utils_spec.lua62
8 files changed, 827 insertions, 64 deletions
diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua
index 39b6ddc105..4e90c2fd1b 100644
--- a/test/functional/plugin/lsp/completion_spec.lua
+++ b/test/functional/plugin/lsp/completion_spec.lua
@@ -216,6 +216,43 @@ describe('vim.lsp.completion: item conversion', function()
})
end)
+ it('uses filterText as word if label/newText would not match', function()
+ local items = {
+ {
+ filterText = '<module',
+ insertTextFormat = 2,
+ kind = 10,
+ label = 'module',
+ sortText = 'module',
+ textEdit = {
+ newText = '<module>$1</module>$0',
+ range = {
+ start = {
+ character = 0,
+ line = 0,
+ },
+ ['end'] = {
+ character = 0,
+ line = 0,
+ },
+ },
+ },
+ },
+ }
+ assert_completion_matches('<mo', items, {
+ {
+ abbr = 'module',
+ word = '<module',
+ },
+ })
+ assert_completion_matches('', items, {
+ {
+ abbr = 'module',
+ word = 'module',
+ },
+ })
+ end)
+
it('fuzzy matches on label when filterText is missing', function()
assert_completion_matches('fo', {
{ label = 'foo' },
@@ -731,9 +768,10 @@ describe('vim.lsp.completion: item conversion', function()
)
end)
+--- @param name string
--- @param completion_result lsp.CompletionList
--- @return integer
-local function create_server(completion_result)
+local function create_server(name, completion_result)
return exec_lua(function()
local server = _G._create_server({
capabilities = {
@@ -751,7 +789,7 @@ local function create_server(completion_result)
local bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
return vim.lsp.start({
- name = 'dummy',
+ name = name,
cmd = server.cmd,
on_attach = function(client, bufnr0)
vim.lsp.completion.enable(true, client.id, bufnr0, {
@@ -800,7 +838,7 @@ describe('vim.lsp.completion: protocol', function()
end
it('fetches completions and shows them using complete on trigger', function()
- create_server({
+ create_server('dummy', {
isIncomplete = false,
items = {
{
@@ -892,7 +930,7 @@ describe('vim.lsp.completion: protocol', function()
end)
it('merges results from multiple clients', function()
- create_server({
+ create_server('dummy1', {
isIncomplete = false,
items = {
{
@@ -900,7 +938,7 @@ describe('vim.lsp.completion: protocol', function()
},
},
})
- create_server({
+ create_server('dummy2', {
isIncomplete = false,
items = {
{
@@ -933,7 +971,7 @@ describe('vim.lsp.completion: protocol', function()
},
},
}
- local client_id = create_server(completion_list)
+ local client_id = create_server('dummy', completion_list)
exec_lua(function()
_G.called = false
@@ -970,7 +1008,7 @@ describe('vim.lsp.completion: protocol', function()
end)
it('enable(…,{convert=fn}) custom word/abbr format', function()
- create_server({
+ create_server('dummy', {
isIncomplete = false,
items = {
{
@@ -1012,7 +1050,7 @@ describe('vim.lsp.completion: integration', function()
exec_lua(function()
vim.o.completeopt = 'menuone,noselect'
end)
- create_server(completion_list)
+ create_server('dummy', completion_list)
feed('i world<esc>0ih<c-x><c-o>')
retry(nil, nil, function()
eq(
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 5afbe22793..4ecb056d01 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -89,7 +89,7 @@ describe('vim.lsp.diagnostic', function()
return extmarks
end
- client_id = assert(vim.lsp.start_client {
+ client_id = assert(vim.lsp.start({
cmd_env = {
NVIM_LUA_NOTRACK = '1',
},
@@ -101,7 +101,7 @@ describe('vim.lsp.diagnostic', function()
'--headless',
},
offset_encoding = 'utf-16',
- })
+ }, { attach = false }))
end)
fake_uri = 'file:///fake/uri'
@@ -209,10 +209,16 @@ describe('vim.lsp.diagnostic', function()
before_each(function()
exec_lua(create_server_definition)
exec_lua(function()
+ _G.requests = 0
_G.server = _G._create_server({
capabilities = {
diagnosticProvider = {},
},
+ handlers = {
+ [vim.lsp.protocol.Methods.textDocument_diagnostic] = function()
+ _G.requests = _G.requests + 1
+ end,
+ },
})
function _G.get_extmarks(bufnr, client_id0)
@@ -373,5 +379,56 @@ describe('vim.lsp.diagnostic', function()
end)
)
end)
+
+ it('handles server cancellation', function()
+ eq(
+ 1,
+ exec_lua(function()
+ vim.lsp.diagnostic.on_diagnostic({
+ code = vim.lsp.protocol.ErrorCodes.ServerCancelled,
+ -- Empty data defaults to retriggering request
+ data = {},
+ message = '',
+ }, {}, {
+ method = vim.lsp.protocol.Methods.textDocument_diagnostic,
+ client_id = client_id,
+ })
+
+ return _G.requests
+ end)
+ )
+
+ eq(
+ 2,
+ exec_lua(function()
+ vim.lsp.diagnostic.on_diagnostic({
+ code = vim.lsp.protocol.ErrorCodes.ServerCancelled,
+ data = { retriggerRequest = true },
+ message = '',
+ }, {}, {
+ method = vim.lsp.protocol.Methods.textDocument_diagnostic,
+ client_id = client_id,
+ })
+
+ return _G.requests
+ end)
+ )
+
+ eq(
+ 2,
+ exec_lua(function()
+ vim.lsp.diagnostic.on_diagnostic({
+ code = vim.lsp.protocol.ErrorCodes.ServerCancelled,
+ data = { retriggerRequest = false },
+ message = '',
+ }, {}, {
+ method = vim.lsp.protocol.Methods.textDocument_diagnostic,
+ client_id = client_id,
+ })
+
+ return _G.requests
+ end)
+ )
+ end)
end)
end)
diff --git a/test/functional/plugin/lsp/folding_range_spec.lua b/test/functional/plugin/lsp/folding_range_spec.lua
new file mode 100644
index 0000000000..7e68a598d2
--- /dev/null
+++ b/test/functional/plugin/lsp/folding_range_spec.lua
@@ -0,0 +1,647 @@
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+local Screen = require('test.functional.ui.screen')
+local t_lsp = require('test.functional.plugin.lsp.testutil')
+
+local eq = t.eq
+local tempname = t.tmpname
+
+local clear_notrace = t_lsp.clear_notrace
+local create_server_definition = t_lsp.create_server_definition
+
+local api = n.api
+local exec_lua = n.exec_lua
+local insert = n.insert
+local command = n.command
+local feed = n.feed
+
+describe('vim.lsp.folding_range', function()
+ local text = [[// foldLevel() {{{2
+/// @return fold level at line number "lnum" in the current window.
+static int foldLevel(linenr_T lnum)
+{
+ // While updating the folds lines between invalid_top and invalid_bot have
+ // an undefined fold level. Otherwise update the folds first.
+ if (invalid_top == 0) {
+ checkupdate(curwin);
+ } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) {
+ return prev_lnum_lvl;
+ } else if (lnum >= invalid_top && lnum <= invalid_bot) {
+ return -1;
+ }
+
+ // Return quickly when there is no folding at all in this window.
+ if (!hasAnyFolding(curwin)) {
+ return 0;
+ }
+
+ return foldLevelWin(curwin, lnum);
+}]]
+
+ local result = {
+ {
+ endLine = 19,
+ kind = 'region',
+ startCharacter = 1,
+ startLine = 3,
+ },
+ {
+ endCharacter = 2,
+ endLine = 7,
+ kind = 'region',
+ startCharacter = 25,
+ startLine = 6,
+ },
+ {
+ endCharacter = 2,
+ endLine = 9,
+ kind = 'region',
+ startCharacter = 55,
+ startLine = 8,
+ },
+ {
+ endCharacter = 2,
+ endLine = 11,
+ kind = 'region',
+ startCharacter = 58,
+ startLine = 10,
+ },
+ {
+ endCharacter = 2,
+ endLine = 16,
+ kind = 'region',
+ startCharacter = 31,
+ startLine = 15,
+ },
+ {
+ endCharacter = 68,
+ endLine = 1,
+ kind = 'comment',
+ startCharacter = 2,
+ startLine = 0,
+ },
+ {
+ endCharacter = 64,
+ endLine = 5,
+ kind = 'comment',
+ startCharacter = 4,
+ startLine = 4,
+ },
+ }
+
+ local bufnr ---@type integer
+ local client_id ---@type integer
+
+ clear_notrace()
+ before_each(function()
+ clear_notrace()
+
+ exec_lua(create_server_definition)
+ bufnr = n.api.nvim_get_current_buf()
+ client_id = exec_lua(function()
+ _G.server = _G._create_server({
+ capabilities = {
+ foldingRangeProvider = true,
+ },
+ handlers = {
+ ['textDocument/foldingRange'] = function(_, _, callback)
+ callback(nil, result)
+ end,
+ },
+ })
+
+ vim.api.nvim_win_set_buf(0, bufnr)
+
+ return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd })
+ end)
+ command('set foldmethod=expr foldcolumn=1 foldlevel=999')
+ insert(text)
+ end)
+ after_each(function()
+ api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
+ end)
+
+ describe('setup()', function()
+ ---@type integer
+ local bufnr_set_expr
+ ---@type integer
+ local bufnr_never_set_expr
+
+ local function buf_autocmd_num(bufnr_to_check)
+ return exec_lua(function()
+ return #vim.api.nvim_get_autocmds({ buffer = bufnr_to_check, event = 'LspNotify' })
+ end)
+ end
+
+ before_each(function()
+ command([[setlocal foldexpr=v:lua.vim.lsp.foldexpr()]])
+ exec_lua(function()
+ bufnr_set_expr = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_set_current_buf(bufnr_set_expr)
+ end)
+ insert(text)
+ command('write ' .. tempname(false))
+ command([[setlocal foldexpr=v:lua.vim.lsp.foldexpr()]])
+ exec_lua(function()
+ bufnr_never_set_expr = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_set_current_buf(bufnr_never_set_expr)
+ end)
+ insert(text)
+ api.nvim_win_set_buf(0, bufnr_set_expr)
+ end)
+
+ it('only create event hooks where foldexpr has been set', function()
+ eq(1, buf_autocmd_num(bufnr))
+ eq(1, buf_autocmd_num(bufnr_set_expr))
+ eq(0, buf_autocmd_num(bufnr_never_set_expr))
+ end)
+
+ it('does not create duplicate event hooks after reloaded', function()
+ command('edit')
+ eq(1, buf_autocmd_num(bufnr_set_expr))
+ end)
+
+ it('cleans up event hooks when buffer is unloaded', function()
+ command('bdelete')
+ eq(0, buf_autocmd_num(bufnr_set_expr))
+ end)
+ end)
+
+ describe('expr()', function()
+ --- @type test.functional.ui.screen
+ local screen
+ before_each(function()
+ screen = Screen.new(80, 45)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, reverse = true },
+ [4] = { reverse = true },
+ })
+ command([[set foldexpr=v:lua.vim.lsp.foldexpr()]])
+ command([[split]])
+ end)
+
+ it('can compute fold levels', function()
+ ---@type table<integer, string>
+ local foldlevels = {}
+ for i = 1, 21 do
+ foldlevels[i] = exec_lua('return vim.lsp.foldexpr(' .. i .. ')')
+ end
+ eq({
+ [1] = '>1',
+ [2] = '<1',
+ [3] = '0',
+ [4] = '>1',
+ [5] = '>2',
+ [6] = '<2',
+ [7] = '>2',
+ [8] = '<2',
+ [9] = '>2',
+ [10] = '<2',
+ [11] = '>2',
+ [12] = '<2',
+ [13] = '1',
+ [14] = '1',
+ [15] = '1',
+ [16] = '>2',
+ [17] = '<2',
+ [18] = '1',
+ [19] = '1',
+ [20] = '<1',
+ [21] = '0',
+ }, foldlevels)
+ end)
+
+ it('updates folds in all windows', function()
+ screen:expect({
+ grid = [[
+{1:-}// foldLevel() {{{2 |
+{1:│}/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }^} |
+{3:[No Name] [+] }|
+{1:-}// foldLevel() {{{2 |
+{1:│}/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }} |
+{4:[No Name] [+] }|
+ |
+ ]],
+ })
+ end)
+
+ it('persists wherever foldexpr is set', function()
+ command([[setlocal foldexpr=]])
+ feed('<C-w><C-w>zx')
+ screen:expect({
+ grid = [[
+{1: }// foldLevel() {{{2 |
+{1: }/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1: }{ |
+{1: } // While updating the folds lines between invalid_top and invalid_bot have |
+{1: } // an undefined fold level. Otherwise update the folds first. |
+{1: } if (invalid_top == 0) { |
+{1: } checkupdate(curwin); |
+{1: } } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1: } return prev_lnum_lvl; |
+{1: } } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1: } return -1; |
+{1: } } |
+{1: } |
+{1: } // Return quickly when there is no folding at all in this window. |
+{1: } if (!hasAnyFolding(curwin)) { |
+{1: } return 0; |
+{1: } } |
+{1: } |
+{1: } return foldLevelWin(curwin, lnum); |
+{1: }} |
+{4:[No Name] [+] }|
+{1:-}// foldLevel() {{{2 |
+{1:│}/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }^} |
+{3:[No Name] [+] }|
+ |
+ ]],
+ })
+ end)
+
+ it('synchronizes changed rows with their previous foldlevels', function()
+ command('1,2d')
+ screen:expect({
+ grid = [[
+{1: }^static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }} |
+{2:~ }|*2
+{3:[No Name] [+] }|
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }} |
+{2:~ }|*2
+{4:[No Name] [+] }|
+ |
+]],
+ })
+ end)
+
+ it('clears folds when sole client detaches', function()
+ exec_lua(function()
+ vim.lsp.buf_detach_client(bufnr, client_id)
+ end)
+ screen:expect({
+ grid = [[
+{1: }// foldLevel() {{{2 |
+{1: }/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1: }{ |
+{1: } // While updating the folds lines between invalid_top and invalid_bot have |
+{1: } // an undefined fold level. Otherwise update the folds first. |
+{1: } if (invalid_top == 0) { |
+{1: } checkupdate(curwin); |
+{1: } } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1: } return prev_lnum_lvl; |
+{1: } } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1: } return -1; |
+{1: } } |
+{1: } |
+{1: } // Return quickly when there is no folding at all in this window. |
+{1: } if (!hasAnyFolding(curwin)) { |
+{1: } return 0; |
+{1: } } |
+{1: } |
+{1: } return foldLevelWin(curwin, lnum); |
+{1: }^} |
+{3:[No Name] [+] }|
+{1: }// foldLevel() {{{2 |
+{1: }/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1: }{ |
+{1: } // While updating the folds lines between invalid_top and invalid_bot have |
+{1: } // an undefined fold level. Otherwise update the folds first. |
+{1: } if (invalid_top == 0) { |
+{1: } checkupdate(curwin); |
+{1: } } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1: } return prev_lnum_lvl; |
+{1: } } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1: } return -1; |
+{1: } } |
+{1: } |
+{1: } // Return quickly when there is no folding at all in this window. |
+{1: } if (!hasAnyFolding(curwin)) { |
+{1: } return 0; |
+{1: } } |
+{1: } |
+{1: } return foldLevelWin(curwin, lnum); |
+{1: }} |
+{4:[No Name] [+] }|
+ |
+ ]],
+ })
+ end)
+
+ it('remains valid after the client re-attaches.', function()
+ exec_lua(function()
+ vim.lsp.buf_detach_client(bufnr, client_id)
+ vim.lsp.buf_attach_client(bufnr, client_id)
+ end)
+ screen:expect({
+ grid = [[
+{1:-}// foldLevel() {{{2 |
+{1:│}/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }^} |
+{3:[No Name] [+] }|
+{1:-}// foldLevel() {{{2 |
+{1:│}/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:-} // While updating the folds lines between invalid_top and invalid_bot have |
+{1:2} // an undefined fold level. Otherwise update the folds first. |
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }} |
+{4:[No Name] [+] }|
+ |
+ ]],
+ })
+ end)
+ end)
+
+ describe('foldtext()', function()
+ --- @type test.functional.ui.screen
+ local screen
+ before_each(function()
+ screen = Screen.new(80, 23)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey },
+ [3] = { bold = true, foreground = Screen.colors.Blue1 },
+ [4] = { bold = true, reverse = true },
+ [5] = { reverse = true },
+ })
+ command(
+ [[set foldexpr=v:lua.vim.lsp.foldexpr() foldtext=v:lua.vim.lsp.foldtext() foldlevel=1]]
+ )
+ end)
+
+ it('shows the first folded line if `collapsedText` does not exist', function()
+ screen:expect({
+ grid = [[
+{1:-}// foldLevel() {{{2 |
+{1:│}/// @return fold level at line number "lnum" in the current window. |
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:+}{2: // While updating the folds lines between invalid_top and invalid_bot have···}|
+{1:+}{2: if (invalid_top == 0) {······················································}|
+{1:+}{2: } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) {························}|
+{1:+}{2: } else if (lnum >= invalid_top && lnum <= invalid_bot) {·····················}|
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:+}{2: if (!hasAnyFolding(curwin)) {················································}|
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }^} |
+{3:~ }|*6
+ |
+ ]],
+ })
+ end)
+ end)
+
+ describe('foldclose()', function()
+ --- @type test.functional.ui.screen
+ local screen
+ before_each(function()
+ screen = Screen.new(80, 23)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey },
+ [3] = { bold = true, foreground = Screen.colors.Blue1 },
+ [4] = { bold = true, reverse = true },
+ [5] = { reverse = true },
+ })
+ command([[set foldexpr=v:lua.vim.lsp.foldexpr()]])
+ end)
+
+ it('closes all folds of one kind immediately', function()
+ exec_lua(function()
+ vim.lsp.foldclose('comment')
+ end)
+ screen:expect({
+ grid = [[
+{1:+}{2:+-- 2 lines: foldLevel()······················································}|
+{1: }static int foldLevel(linenr_T lnum) |
+{1:-}{ |
+{1:+}{2:+--- 2 lines: While updating the folds lines between invalid_top and invalid_b}|
+{1:-} if (invalid_top == 0) { |
+{1:2} checkupdate(curwin); |
+{1:-} } else if (lnum == prev_lnum && prev_lnum_lvl >= 0) { |
+{1:2} return prev_lnum_lvl; |
+{1:-} } else if (lnum >= invalid_top && lnum <= invalid_bot) { |
+{1:2} return -1; |
+{1:│} } |
+{1:│} |
+{1:│} // Return quickly when there is no folding at all in this window. |
+{1:-} if (!hasAnyFolding(curwin)) { |
+{1:2} return 0; |
+{1:│} } |
+{1:│} |
+{1:│} return foldLevelWin(curwin, lnum); |
+{1: }^} |
+{3:~ }|*3
+ |
+ ]],
+ })
+ end)
+
+ it('closes the smallest fold first', function()
+ exec_lua(function()
+ vim.lsp.foldclose('region')
+ end)
+ screen:expect({
+ grid = [[
+{1:-}// foldLevel() {{{2 |