aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
committerJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
commitff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch)
tree729bbcb92231538fa61dab6c3d890b025484b7f5 /test/functional/plugin
parent376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff)
parent28c04948a1c887a1cc0cb64de79fa32631700466 (diff)
downloadrneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.gz
rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.bz2
rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'test/functional/plugin')
-rw-r--r--test/functional/plugin/ccomplete_spec.lua16
-rw-r--r--test/functional/plugin/cfilter_spec.lua12
-rw-r--r--test/functional/plugin/editorconfig_spec.lua34
-rw-r--r--test/functional/plugin/health_spec.lua126
-rw-r--r--test/functional/plugin/lsp/codelens_spec.lua11
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua10
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua26
-rw-r--r--test/functional/plugin/lsp/handler_spec.lua11
-rw-r--r--test/functional/plugin/lsp/incremental_sync_spec.lua13
-rw-r--r--test/functional/plugin/lsp/inlay_hint_spec.lua122
-rw-r--r--test/functional/plugin/lsp/semantic_tokens_spec.lua194
-rw-r--r--test/functional/plugin/lsp/snippet_spec.lua12
-rw-r--r--test/functional/plugin/lsp/testutil.lua (renamed from test/functional/plugin/lsp/helpers.lua)44
-rw-r--r--test/functional/plugin/lsp/utils_spec.lua13
-rw-r--r--test/functional/plugin/lsp_spec.lua1011
-rw-r--r--test/functional/plugin/man_spec.lua41
-rw-r--r--test/functional/plugin/matchparen_spec.lua15
-rw-r--r--test/functional/plugin/msgpack_spec.lua18
-rw-r--r--test/functional/plugin/shada_spec.lua18
-rw-r--r--test/functional/plugin/tohtml_spec.lua17
-rw-r--r--test/functional/plugin/tutor_spec.lua175
-rw-r--r--test/functional/plugin/vim_syntax_spec.lua13
22 files changed, 1379 insertions, 573 deletions
diff --git a/test/functional/plugin/ccomplete_spec.lua b/test/functional/plugin/ccomplete_spec.lua
index 903f16fc73..4c4c5e9444 100644
--- a/test/functional/plugin/ccomplete_spec.lua
+++ b/test/functional/plugin/ccomplete_spec.lua
@@ -1,10 +1,12 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local command = helpers.command
-local eq = helpers.eq
-local eval = helpers.eval
-local feed = helpers.feed
-local write_file = helpers.write_file
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local command = n.command
+local eq = t.eq
+local eval = n.eval
+local feed = n.feed
+local write_file = t.write_file
describe('ccomplete#Complete', function()
setup(function()
diff --git a/test/functional/plugin/cfilter_spec.lua b/test/functional/plugin/cfilter_spec.lua
index 37261d59df..220404a934 100644
--- a/test/functional/plugin/cfilter_spec.lua
+++ b/test/functional/plugin/cfilter_spec.lua
@@ -1,8 +1,10 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local command = helpers.command
-local eq = helpers.eq
-local fn = helpers.fn
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local command = n.command
+local eq = t.eq
+local fn = n.fn
describe('cfilter.lua', function()
before_each(function()
diff --git a/test/functional/plugin/editorconfig_spec.lua b/test/functional/plugin/editorconfig_spec.lua
index 115c28fbf6..839a723405 100644
--- a/test/functional/plugin/editorconfig_spec.lua
+++ b/test/functional/plugin/editorconfig_spec.lua
@@ -1,14 +1,18 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local command = helpers.command
-local eq = helpers.eq
-local pathsep = helpers.get_pathsep()
-local fn = helpers.fn
-local api = helpers.api
-local exec_lua = helpers.exec_lua
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local command = n.command
+local eq = t.eq
+local pathsep = n.get_pathsep()
+local fn = n.fn
+local api = n.api
+local exec_lua = n.exec_lua
local testdir = 'Xtest-editorconfig'
+--- @param name string
+--- @param expected table<string,any>
local function test_case(name, expected)
local filename = testdir .. pathsep .. name
command('edit ' .. filename)
@@ -18,8 +22,8 @@ local function test_case(name, expected)
end
setup(function()
- helpers.mkdir_p(testdir)
- helpers.write_file(
+ n.mkdir_p(testdir)
+ t.write_file(
testdir .. pathsep .. '.editorconfig',
[[
root = true
@@ -94,7 +98,7 @@ setup(function()
end)
teardown(function()
- helpers.rmdir(testdir)
+ n.rmdir(testdir)
end)
describe('editorconfig', function()
@@ -176,18 +180,18 @@ But not this one
-- luacheck: pop
local trimmed = untrimmed:gsub('%s+\n', '\n')
- helpers.write_file(filename, untrimmed)
+ t.write_file(filename, untrimmed)
command('edit ' .. filename)
command('write')
command('bdelete')
- eq(trimmed, helpers.read_file(filename))
+ eq(trimmed, t.read_file(filename))
filename = testdir .. pathsep .. 'no_trim.txt'
- helpers.write_file(filename, untrimmed)
+ t.write_file(filename, untrimmed)
command('edit ' .. filename)
command('write')
command('bdelete')
- eq(untrimmed, helpers.read_file(filename))
+ eq(untrimmed, t.read_file(filename))
end)
it('sets textwidth', function()
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index 8564ec7c9b..9c7c953fb0 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -1,14 +1,18 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local clear = helpers.clear
-local curbuf_contents = helpers.curbuf_contents
-local command = helpers.command
-local eq, neq, matches = helpers.eq, helpers.neq, helpers.matches
-local getcompletion = helpers.fn.getcompletion
-local insert = helpers.insert
-local source = helpers.source
-local exec_lua = helpers.exec_lua
+local clear = n.clear
+local curbuf_contents = n.curbuf_contents
+local command = n.command
+local eq, matches = t.eq, t.matches
+local getcompletion = n.fn.getcompletion
+local insert = n.insert
+local exec_lua = n.exec_lua
+local source = n.source
+local assert_alive = n.assert_alive
+local fn = n.fn
+local api = n.api
describe(':checkhealth', function()
it('detects invalid $VIMRUNTIME', function()
@@ -19,6 +23,7 @@ describe(':checkhealth', function()
eq(false, status)
eq('Invalid $VIMRUNTIME: bogus', string.match(err, 'Invalid.*'))
end)
+
it("detects invalid 'runtimepath'", function()
clear()
command('set runtimepath=bogus')
@@ -26,19 +31,29 @@ describe(':checkhealth', function()
eq(false, status)
eq("Invalid 'runtimepath'", string.match(err, 'Invalid.*'))
end)
+
it('detects invalid $VIM', function()
clear()
-- Do this after startup, otherwise it just breaks $VIMRUNTIME.
command("let $VIM='zub'")
- command('checkhealth nvim')
+ command('checkhealth vim.health')
matches('ERROR $VIM .* zub', curbuf_contents())
end)
+
it('completions can be listed via getcompletion()', function()
clear()
- eq('nvim', getcompletion('nvim', 'checkhealth')[1])
- eq('provider.clipboard', getcompletion('prov', 'checkhealth')[1])
+ eq('vim.deprecated', getcompletion('vim', 'checkhealth')[1])
+ eq('vim.provider', getcompletion('vim.prov', 'checkhealth')[1])
eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
- neq('vim', getcompletion('^vim', 'checkhealth')[1]) -- should not complete vim.health
+ end)
+
+ it('completion checks for vim.health._complete() return type #28456', function()
+ clear()
+ exec_lua([[vim.health._complete = function() return 1 end]])
+ eq({}, getcompletion('', 'checkhealth'))
+ exec_lua([[vim.health._complete = function() return { 1 } end]])
+ eq({}, getcompletion('', 'checkhealth'))
+ assert_alive()
end)
end)
@@ -52,7 +67,7 @@ describe('health.vim', function()
describe(':checkhealth', function()
it('functions report_*() render correctly', function()
command('checkhealth full_render')
- helpers.expect([[
+ n.expect([[
==============================================================================
test_plug.full_render: require("test_plug.full_render.health").check()
@@ -75,7 +90,7 @@ describe('health.vim', function()
it('concatenates multiple reports', function()
command('checkhealth success1 success2 test_plug')
- helpers.expect([[
+ n.expect([[
==============================================================================
test_plug: require("test_plug.health").check()
@@ -105,7 +120,7 @@ describe('health.vim', function()
it('lua plugins submodules', function()
command('checkhealth test_plug.submodule')
- helpers.expect([[
+ n.expect([[
==============================================================================
test_plug.submodule: require("test_plug.submodule.health").check()
@@ -120,7 +135,7 @@ describe('health.vim', function()
it('... including empty reports', function()
command('checkhealth test_plug.submodule_empty')
- helpers.expect([[
+ n.expect([[
==============================================================================
test_plug.submodule_empty: require("test_plug.submodule_empty.health").check()
@@ -158,28 +173,10 @@ describe('health.vim', function()
}
end)
- it('fold healthchecks', function()
- local screen = Screen.new(50, 7)
- screen:attach()
- command('checkhealth foo success1')
- command('set nowrap laststatus=0')
- screen:expect {
- grid = [[
- ^ |
- ──────────────────────────────────────────────────|
- +WE 4 lines: foo: ·······························|
- ──────────────────────────────────────────────────|
- +-- 8 lines: test_plug.success1: require("test_pl|
- ~ |
- |
- ]],
- }
- end)
-
it('gracefully handles invalid healthcheck', function()
command('checkhealth non_existent_healthcheck')
-- luacheck: ignore 613
- helpers.expect([[
+ n.expect([[
==============================================================================
non_existent_healthcheck:
@@ -191,7 +188,7 @@ describe('health.vim', function()
it('does not use vim.health as a healtcheck', function()
-- vim.health is not a healthcheck
command('checkhealth vim')
- helpers.expect([[
+ n.expect([[
ERROR: No healthchecks found.]])
end)
end)
@@ -218,6 +215,12 @@ describe(':checkhealth window', function()
it('opens directly if no buffer created', function()
local screen = Screen.new(50, 12)
+ screen:set_default_attr_ids {
+ [1] = { foreground = Screen.colors.Blue, bold = true },
+ [14] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray },
+ [31] = { foreground = tonumber('0x6a0dad') },
+ [32] = { foreground = Screen.colors.PaleGreen2 },
+ }
screen:attach({ ext_multigrid = true })
command('checkhealth success1')
screen:expect {
@@ -227,16 +230,16 @@ describe(':checkhealth window', function()
[3:--------------------------------------------------]|
## grid 2
^ |
- ──────────────────────────────────────────────────|
- ──────────────────────────── |
- test_plug.success1: require("test_plug.success1. |
- health").check() |
+ {14:──────────────────────────────────────────────────}|
+ {14:────────────────────────────} |
+ {31:test_plug.success1: require("test_plug.success1. }|
+ {31:health").check()} |
|
- report 1 |
- - OK everything is fine |
+ {31:report 1} |
+ - {32:OK} everything is fine |
|
- report 2 |
- - OK nothing to see here |
+ {31:report 2} |
+ - {32:OK} nothing to see here |
## grid 3
|
]],
@@ -245,6 +248,12 @@ describe(':checkhealth window', function()
local function test_health_vsplit(left, emptybuf, mods)
local screen = Screen.new(50, 20)
+ screen:set_default_attr_ids {
+ [1] = { foreground = Screen.colors.Blue, bold = true },
+ [14] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray },
+ [31] = { foreground = tonumber('0x6a0dad') },
+ [32] = { foreground = Screen.colors.PaleGreen2 },
+ }
screen:attach({ ext_multigrid = true })
if not emptybuf then
insert('hello')
@@ -257,24 +266,24 @@ describe(':checkhealth window', function()
[3:--------------------------------------------------]|
## grid 2
%s |
- ~ |*18
+ {1:~ }|*18
## grid 3
|
## grid 4
^ |
- ─────────────────────────|*3
- ─── |
- test_plug.success1: |
- require("test_plug. |
- success1.health").check()|
+ {14:─────────────────────────}|*3
+ {14:───} |
+ {31:test_plug.success1: }|
+ {31:require("test_plug. }|
+ {31:success1.health").check()}|
|
- report 1 |
- - OK everything is fine |
+ {31:report 1} |
+ - {32:OK} everything is fine |
|
- report 2 |
- - OK nothing to see here |
+ {31:report 2} |
+ - {32:OK} nothing to see here |
|
- ~ |*4
+ {1:~ }|*4
]]):format(
left and '[4:-------------------------]│[2:------------------------]|*19'
or '[2:------------------------]│[4:-------------------------]|*19',
@@ -304,6 +313,7 @@ describe(':checkhealth window', function()
local function test_health_split(top, emptybuf, mods)
local screen = Screen.new(50, 25)
screen:attach({ ext_multigrid = true })
+ screen._default_attr_ids = nil
if not emptybuf then
insert('hello')
end
@@ -368,7 +378,7 @@ describe(':checkhealth window', function()
it('opens in tab', function()
-- create an empty buffer called "my_buff"
- exec_lua 'vim.api.nvim_create_buf(false, true)'
+ api.nvim_create_buf(false, true)
command('file my_buff')
command('checkhealth success1')
-- define a function that collects all buffers in each tab
@@ -387,7 +397,7 @@ describe(':checkhealth window', function()
return buffs
endfunction
]])
- local buffers_per_tab = exec_lua('return vim.fn.CollectBuffersPerTab()')
+ local buffers_per_tab = fn.CollectBuffersPerTab()
eq(buffers_per_tab, { tab1 = { 'my_buff' }, tab2 = { 'health://' } })
end)
end)
diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua
index 29daf7a066..cd20e95dd1 100644
--- a/test/functional/plugin/lsp/codelens_spec.lua
+++ b/test/functional/plugin/lsp/codelens_spec.lua
@@ -1,14 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
+local exec_lua = n.exec_lua
+local eq = t.eq
describe('vim.lsp.codelens', function()
before_each(function()
- helpers.clear()
+ n.clear()
exec_lua('require("vim.lsp")')
end)
- after_each(helpers.clear)
+ after_each(n.clear)
it('on_codelens_stores_and_displays_lenses', function()
local fake_uri = 'file:///fake/uri'
diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua
index 655eb76be6..2798d57381 100644
--- a/test/functional/plugin/lsp/completion_spec.lua
+++ b/test/functional/plugin/lsp/completion_spec.lua
@@ -1,7 +1,9 @@
---@diagnostic disable: no-unknown
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local eq = t.eq
+local exec_lua = n.exec_lua
--- Convert completion results.
---
@@ -41,7 +43,7 @@ local function complete(line, candidates, lnum)
end
describe('vim.lsp._completion', function()
- before_each(helpers.clear)
+ before_each(n.clear)
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
it('prefers textEdit over label as word', function()
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 705c182df7..c5e14ffdc2 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -1,12 +1,14 @@
-local helpers = require('test.functional.helpers')(after_each)
-local lsp_helpers = require('test.functional.plugin.lsp.helpers')
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local neq = require('test.helpers').neq
+local t_lsp = require('test.functional.plugin.lsp.testutil')
-local create_server_definition = lsp_helpers.create_server_definition
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local neq = t.neq
+
+local create_server_definition = t_lsp.create_server_definition
describe('vim.lsp.diagnostic', function()
local fake_uri
@@ -257,7 +259,7 @@ describe('vim.lsp.diagnostic', function()
}, {client_id=client_id})
return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2"))
]]
- eq(bufnr, -1)
+ eq(-1, bufnr)
-- Create buffer on diagnostics
bufnr = exec_lua [[
@@ -269,8 +271,8 @@ describe('vim.lsp.diagnostic', function()
}, {client_id=client_id})
return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2"))
]]
- neq(bufnr, -1)
- eq(exec_lua([[return #vim.diagnostic.get(...)]], bufnr), 1)
+ neq(-1, bufnr)
+ eq(1, exec_lua([[return #vim.diagnostic.get(...)]], bufnr))
-- Clear diagnostics after buffer was created
bufnr = exec_lua [[
@@ -280,8 +282,8 @@ describe('vim.lsp.diagnostic', function()
}, {client_id=client_id})
return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2"))
]]
- neq(bufnr, -1)
- eq(exec_lua([[return #vim.diagnostic.get(...)]], bufnr), 0)
+ neq(-1, bufnr)
+ eq(0, exec_lua([[return #vim.diagnostic.get(...)]], bufnr))
end)
end)
diff --git a/test/functional/plugin/lsp/handler_spec.lua b/test/functional/plugin/lsp/handler_spec.lua
index 56e29e7337..013a5fb5e7 100644
--- a/test/functional/plugin/lsp/handler_spec.lua
+++ b/test/functional/plugin/lsp/handler_spec.lua
@@ -1,9 +1,10 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local pcall_err = helpers.pcall_err
-local matches = helpers.matches
+local eq = t.eq
+local exec_lua = n.exec_lua
+local pcall_err = t.pcall_err
+local matches = t.matches
describe('lsp-handlers', function()
describe('vim.lsp._with_extend', function()
diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua
index bd1842ceb5..238b90b57d 100644
--- a/test/functional/plugin/lsp/incremental_sync_spec.lua
+++ b/test/functional/plugin/lsp/incremental_sync_spec.lua
@@ -1,11 +1,12 @@
-- Test suite for testing interactions with the incremental sync algorithms powering the LSP client
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local api = helpers.api
-local clear = helpers.clear
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local feed = helpers.feed
+local api = n.api
+local clear = n.clear
+local eq = t.eq
+local exec_lua = n.exec_lua
+local feed = n.feed
before_each(function()
clear()
diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua
index 192797b312..d3b5ae0e4e 100644
--- a/test/functional/plugin/lsp/inlay_hint_spec.lua
+++ b/test/functional/plugin/lsp/inlay_hint_spec.lua
@@ -1,14 +1,16 @@
-local helpers = require('test.functional.helpers')(after_each)
-local lsp_helpers = require('test.functional.plugin.lsp.helpers')
+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 = helpers.eq
-local dedent = helpers.dedent
-local exec_lua = helpers.exec_lua
-local insert = helpers.insert
+local eq = t.eq
+local dedent = t.dedent
+local exec_lua = n.exec_lua
+local insert = n.insert
+local api = n.api
-local clear_notrace = lsp_helpers.clear_notrace
-local create_server_definition = lsp_helpers.create_server_definition
+local clear_notrace = t_lsp.clear_notrace
+local create_server_definition = t_lsp.create_server_definition
local text = dedent([[
auto add(int a, int b) { return a + b; }
@@ -41,12 +43,12 @@ local grid_without_inlay_hints = [[
]]
local grid_with_inlay_hints = [[
- auto add(int a, int b)-> int { return a + b; } |
+ auto add(int a, int b){1:-> int} { return a + b; } |
|
int main() { |
int x = 1; |
int y = 2; |
- return add(a: x,b: y); |
+ return add({1:a:} x,{1:b:} y); |
} |
^} |
|
@@ -68,8 +70,8 @@ before_each(function()
inlayHintProvider = true,
},
handlers = {
- ['textDocument/inlayHint'] = function()
- return vim.json.decode(response)
+ ['textDocument/inlayHint'] = function(_, _, callback)
+ callback(nil, vim.json.decode(response))
end,
}
})
@@ -83,12 +85,12 @@ before_each(function()
)
insert(text)
- exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]])
+ exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })]])
screen:expect({ grid = grid_with_inlay_hints })
end)
after_each(function()
- exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
+ api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
end)
describe('vim.lsp.inlay_hint', function()
@@ -104,13 +106,13 @@ describe('vim.lsp.inlay_hint', function()
inlayHintProvider = true,
},
handlers = {
- ['textDocument/inlayHint'] = function()
- return {}
+ ['textDocument/inlayHint'] = function(_, _, callback)
+ callback(nil, {})
end,
}
})
client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })
- vim.lsp.inlay_hint.enable(bufnr)
+ vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })
]])
exec_lua([[ vim.lsp.stop_client(client2) ]])
@@ -118,18 +120,66 @@ describe('vim.lsp.inlay_hint', function()
end)
describe('enable()', function()
- it('clears/applies inlay hints when passed false/true/nil', function()
- exec_lua([[vim.lsp.inlay_hint.enable(bufnr, false)]])
- screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
+ it('validation', function()
+ t.matches(
+ 'enable: expected boolean, got table',
+ t.pcall_err(exec_lua, [[vim.lsp.inlay_hint.enable({}, { bufnr = bufnr })]])
+ )
+ t.matches(
+ 'enable: expected boolean, got number',
+ t.pcall_err(exec_lua, [[vim.lsp.inlay_hint.enable(42)]])
+ )
+ t.matches(
+ 'filter: expected table, got number',
+ t.pcall_err(exec_lua, [[vim.lsp.inlay_hint.enable(true, 42)]])
+ )
+ end)
+
+ describe('clears/applies inlay hints when passed false/true/nil', function()
+ before_each(function()
+ exec_lua([[
+ bufnr2 = vim.api.nvim_create_buf(true, false)
+ vim.lsp.buf_attach_client(bufnr2, client_id)
+ vim.api.nvim_win_set_buf(0, bufnr2)
+ ]])
+ insert(text)
+ exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr2 })]])
+ exec_lua([[vim.api.nvim_win_set_buf(0, bufnr)]])
+ screen:expect({ grid = grid_with_inlay_hints })
+ end)
+
+ it('for one single buffer', function()
+ exec_lua([[
+ vim.lsp.inlay_hint.enable(false, { bufnr = bufnr })
+ vim.api.nvim_win_set_buf(0, bufnr2)
+ ]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ exec_lua([[vim.api.nvim_win_set_buf(0, bufnr)]])
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
- exec_lua([[vim.lsp.inlay_hint.enable(bufnr, true)]])
- screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
- exec_lua([[vim.lsp.inlay_hint.enable(bufnr, not vim.lsp.inlay_hint.is_enabled(bufnr))]])
- screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
+ exec_lua(
+ [[vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }), { bufnr = bufnr })]]
+ )
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
- exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]])
- screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ end)
+
+ it('for all buffers', function()
+ exec_lua([[vim.lsp.inlay_hint.enable(false)]])
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
+ exec_lua([[vim.api.nvim_win_set_buf(0, bufnr2)]])
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
+
+ exec_lua([[vim.lsp.inlay_hint.enable(true)]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ exec_lua([[vim.api.nvim_win_set_buf(0, bufnr)]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ end)
end)
end)
@@ -156,25 +206,25 @@ describe('vim.lsp.inlay_hint', function()
inlayHintProvider = true,
},
handlers = {
- ['textDocument/inlayHint'] = function()
- return { expected2 }
+ ['textDocument/inlayHint'] = function(_, _, callback)
+ callback(nil, { expected2 })
end,
}
})
client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })
- vim.lsp.inlay_hint.enable(bufnr)
+ vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })
]],
expected2
)
--- @type vim.lsp.inlay_hint.get.ret
local res = exec_lua([[return vim.lsp.inlay_hint.get()]])
- eq(res, {
+ eq({
{ bufnr = 1, client_id = 1, inlay_hint = expected[1] },
{ bufnr = 1, client_id = 1, inlay_hint = expected[2] },
{ bufnr = 1, client_id = 1, inlay_hint = expected[3] },
{ bufnr = 1, client_id = 2, inlay_hint = expected2 },
- })
+ }, res)
--- @type vim.lsp.inlay_hint.get.ret
res = exec_lua([[return vim.lsp.inlay_hint.get({
@@ -183,9 +233,9 @@ describe('vim.lsp.inlay_hint', function()
["end"] = { line = 2, character = 10 },
},
})]])
- eq(res, {
+ eq({
{ bufnr = 1, client_id = 2, inlay_hint = expected2 },
- })
+ }, res)
--- @type vim.lsp.inlay_hint.get.ret
res = exec_lua([[return vim.lsp.inlay_hint.get({
@@ -195,16 +245,16 @@ describe('vim.lsp.inlay_hint', function()
["end"] = { line = 5, character = 17 },
},
})]])
- eq(res, {
+ eq({
{ bufnr = 1, client_id = 1, inlay_hint = expected[2] },
{ bufnr = 1, client_id = 1, inlay_hint = expected[3] },
- })
+ }, res)
--- @type vim.lsp.inlay_hint.get.ret
res = exec_lua([[return vim.lsp.inlay_hint.get({
bufnr = vim.api.nvim_get_current_buf() + 1,
})]])
- eq(res, {})
+ eq({}, res)
end)
end)
end)
diff --git a/test/functional/plugin/lsp/semantic_tokens_spec.lua b/test/functional/plugin/lsp/semantic_tokens_spec.lua
index 77e39c81c8..7908c5d2e7 100644
--- a/test/functional/plugin/lsp/semantic_tokens_spec.lua
+++ b/test/functional/plugin/lsp/semantic_tokens_spec.lua
@@ -1,25 +1,27 @@
-local helpers = require('test.functional.helpers')(after_each)
-local lsp_helpers = require('test.functional.plugin.lsp.helpers')
+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 command = helpers.command
-local dedent = helpers.dedent
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local feed = helpers.feed
-local feed_command = helpers.feed_command
-local insert = helpers.insert
-local matches = helpers.matches
+local command = n.command
+local dedent = t.dedent
+local eq = t.eq
+local exec_lua = n.exec_lua
+local feed = n.feed
+local feed_command = n.feed_command
+local insert = n.insert
+local matches = t.matches
+local api = n.api
-local clear_notrace = lsp_helpers.clear_notrace
-local create_server_definition = lsp_helpers.create_server_definition
+local clear_notrace = t_lsp.clear_notrace
+local create_server_definition = t_lsp.create_server_definition
before_each(function()
clear_notrace()
end)
after_each(function()
- exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
+ api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
end)
describe('semantic token highlighting', function()
@@ -37,6 +39,8 @@ describe('semantic token highlighting', function()
[7] = { bold = true, foreground = Screen.colors.DarkCyan },
[8] = { bold = true, foreground = Screen.colors.SlateBlue },
[9] = { bold = true, foreground = tonumber('0x6a0dad') },
+ [10] = { bold = true, foreground = Screen.colors.Brown },
+ [11] = { foreground = Screen.colors.Magenta1 },
}
command([[ hi link @lsp.type.namespace Type ]])
command([[ hi link @lsp.type.function Special ]])
@@ -91,11 +95,11 @@ describe('semantic token highlighting', function()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(response)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(response))
end,
- ['textDocument/semanticTokens/full/delta'] = function()
- return vim.fn.json_decode(edit_response)
+ ['textDocument/semanticTokens/full/delta'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(edit_response))
end,
}
})
@@ -269,6 +273,63 @@ describe('semantic token highlighting', function()
end
)
+ it('highlights start and stop when using "0" for current buffer', function()
+ exec_lua([[
+ bufnr = vim.api.nvim_get_current_buf()
+ vim.api.nvim_win_set_buf(0, bufnr)
+ client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ ]])
+
+ insert(text)
+
+ exec_lua([[
+ vim.notify = function() end
+ vim.lsp.semantic_tokens.stop(0, client_id)
+ ]])
+
+ screen:expect {
+ grid = [[
+ #include <iostream> |
+ |
+ int main() |
+ { |
+ int x; |
+ #ifdef __cplusplus |
+ std::cout << x << "\n"; |
+ #else |
+ printf("%d\n", x); |
+ #endif |
+ } |
+ ^} |
+ {1:~ }|*3
+ |
+ ]],
+ }
+
+ exec_lua([[
+ vim.lsp.semantic_tokens.start(0, client_id)
+ ]])
+
+ screen:expect {
+ grid = [[
+ #include <iostream> |
+ |
+ int {8:main}() |
+ { |
+ int {7:x}; |
+ #ifdef {5:__cplusplus} |
+ {4:std}::{2:cout} << {2:x} << "\n"; |
+ {6:#else} |
+ {6: printf("%d\n", x);} |
+ {6:#endif} |
+ } |
+ ^} |
+ {1:~ }|*3
+ |
+ ]],
+ }
+ end)
+
it('buffer is re-highlighted when force refreshed', function()
exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
@@ -499,11 +560,11 @@ describe('semantic token highlighting', function()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return nil
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, nil)
end,
['textDocument/semanticTokens/full/delta'] = function()
- return nil
+ callback(nil, nil)
end,
}
})
@@ -547,11 +608,11 @@ describe('semantic token highlighting', function()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(response)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(response))
end,
- ['textDocument/semanticTokens/full/delta'] = function()
- return vim.fn.json_decode(edit_response)
+ ['textDocument/semanticTokens/full/delta'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(edit_response))
end,
}
})
@@ -837,11 +898,13 @@ b = "as"]],
{
it = 'rust-analyzer',
text = [[pub fn main() {
- break rust;
- /// what?
+ println!("Hello world!");
+ break rust;
+ /// what?
}
]],
- response = [[{"data": [0, 0, 3, 1, 0, 0, 4, 2, 1, 0, 0, 3, 4, 14, 524290, 0, 4, 1, 45, 0, 0, 1, 1, 45, 0, 0, 2, 1, 26, 0, 1, 4, 5, 1, 8192, 0, 6, 4, 52, 0, 0, 4, 1, 48, 0, 1, 4, 9, 0, 1, 1, 0, 1, 26, 0], "resultId": "1"}]],
+ response = [[{"data": [0, 0, 3, 1, 0, 0, 4, 2, 1, 0, 0, 3, 4, 14, 524290, 0, 4, 1, 45, 0, 0, 1, 1, 45, 0, 0, 2, 1, 26, 0, 1, 4, 8, 17, 0, 0, 8, 1, 45, 0, 0, 1, 14, 2, 0, 0, 14, 1, 45, 0, 0, 1, 1, 48, 0, 1, 4, 5, 1, 8192, 0, 6, 4, 52, 0, 0, 4, 1, 48, 0, 1, 4, 9, 0, 1, 1, 0, 1, 26, 0 ], "resultId": "1"}]],
+
legend = [[{
"tokenTypes": [
"comment", "keyword", "string", "number", "regexp", "operator", "namespace", "type", "struct", "class", "interface", "enum", "enumMember", "typeParameter", "function", "method", "property", "macro", "variable",
@@ -904,6 +967,46 @@ b = "as"]],
},
{
line = 1,
+ modifiers = {},
+ start_col = 4,
+ end_col = 12,
+ type = 'macro', -- println!
+ marked = true,
+ },
+ {
+ line = 1,
+ modifiers = {},
+ start_col = 12,
+ end_col = 13,
+ type = 'parenthesis',
+ marked = true,
+ },
+ {
+ line = 1,
+ modifiers = {},
+ start_col = 13,
+ end_col = 27,
+ type = 'string', -- "Hello world!"
+ marked = true,
+ },
+ {
+ line = 1,
+ modifiers = {},
+ start_col = 27,
+ end_col = 28,
+ type = 'parenthesis',
+ marked = true,
+ },
+ {
+ line = 1,
+ modifiers = {},
+ start_col = 28,
+ end_col = 29,
+ type = 'semicolon',
+ marked = true,
+ },
+ {
+ line = 2,
modifiers = { controlFlow = true },
start_col = 4,
end_col = 9, -- break
@@ -911,31 +1014,31 @@ b = "as"]],
marked = true,
},
{
- line = 1,
+ line = 2,
modifiers = {},
start_col = 10,
- end_col = 13, -- rust
+ end_col = 14, -- rust
type = 'unresolvedReference',
marked = true,
},
{
- line = 1,
+ line = 2,
modifiers = {},
- start_col = 13,
- end_col = 13,
+ start_col = 14,
+ end_col = 15,
type = 'semicolon',
marked = true,
},
{
- line = 2,
+ line = 3,
modifiers = { documentation = true },
start_col = 4,
- end_col = 11,
+ end_col = 13,
type = 'comment', -- /// what?
marked = true,
},
{
- line = 3,
+ line = 4,
modifiers = {},
start_col = 0,
end_col = 1,
@@ -946,12 +1049,13 @@ b = "as"]],
expected_screen = function()
screen:expect {
grid = [[
- pub fn {8:main}() { |
- break rust; |
- //{6:/ what?} |
+ {10:pub} {10:fn} {8:main}() { |
+ {5:println!}({11:"Hello world!"}); |
+ {10:break} rust; |
+ {6:/// what?} |
} |
^ |
- {1:~ }|*10
+ {1:~ }|*9
|
]],
}
@@ -971,8 +1075,8 @@ b = "as"]],
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(resp)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(resp))
end,
}
})
@@ -1357,11 +1461,11 @@ int main()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(resp1)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(resp1))
end,
- ['textDocument/semanticTokens/full/delta'] = function()
- return vim.fn.json_decode(resp2)
+ ['textDocument/semanticTokens/full/delta'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(resp2))
end,
}
})
diff --git a/test/functional/plugin/lsp/snippet_spec.lua b/test/functional/plugin/lsp/snippet_spec.lua
index ba8bc7fe04..e60c36cd23 100644
--- a/test/functional/plugin/lsp/snippet_spec.lua
+++ b/test/functional/plugin/lsp/snippet_spec.lua
@@ -1,13 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
local snippet = require('vim.lsp._snippet_grammar')
local type = snippet.NodeType
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
+local eq = t.eq
+local exec_lua = n.exec_lua
describe('vim.lsp._snippet_grammar', function()
- before_each(helpers.clear)
- after_each(helpers.clear)
+ before_each(n.clear)
+ after_each(n.clear)
local parse = function(...)
local res = exec_lua('return require("vim.lsp._snippet_grammar").parse(...)', ...)
diff --git a/test/functional/plugin/lsp/helpers.lua b/test/functional/plugin/lsp/testutil.lua
index 97fa108500..3430a1e1a3 100644
--- a/test/functional/plugin/lsp/helpers.lua
+++ b/test/functional/plugin/lsp/testutil.lua
@@ -1,9 +1,10 @@
-local helpers = require('test.functional.helpers')(nil)
+local n = require('test.functional.testnvim')()
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local run = helpers.run
-local stop = helpers.stop
+local clear = n.clear
+local exec_lua = n.exec_lua
+local run = n.run
+local stop = n.stop
+local api = n.api
local NIL = vim.NIL
local M = {}
@@ -38,8 +39,7 @@ M.create_server_definition = [[
})
local handler = handlers[method]
if handler then
- local response, err = handler(method, params)
- callback(err, response)
+ handler(method, params, callback)
elseif method == 'initialize' then
callback(nil, {
capabilities = opts.capabilities or {}
@@ -105,6 +105,11 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options, settings)
uri = 'file://' .. vim.uv.cwd(),
name = 'test_folder',
}};
+ before_init = function(params, config)
+ vim.schedule(function()
+ vim.rpcrequest(1, "setup")
+ end)
+ end,
on_init = function(client, result)
TEST_RPC_CLIENT = client
vim.rpcrequest(1, "init", result)
@@ -128,6 +133,18 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options, settings)
)
end
+--- @class test.lsp.Config
+--- @field test_name string
+--- @field timeout_ms? integer
+--- @field options? table
+--- @field settings? table
+---
+--- @field on_setup? fun()
+--- @field on_init? fun(client: vim.lsp.Client, ...)
+--- @field on_handler? fun(...)
+--- @field on_exit? fun(code: integer, signal: integer)
+
+--- @param config test.lsp.Config
function M.test_rpc_server(config)
if config.test_name then
M.clear_notrace()
@@ -158,8 +175,15 @@ function M.test_rpc_server(config)
end
end,
})
+ --- @type integer, integer
local code, signal
local function on_request(method, args)
+ if method == 'setup' then
+ if config.on_setup then
+ config.on_setup()
+ end
+ return NIL
+ end
if method == 'init' then
if config.on_init then
config.on_init(client, unpack(args))
@@ -180,14 +204,14 @@ function M.test_rpc_server(config)
end
end
-- TODO specify timeout?
- -- run(on_request, on_notify, config.on_setup, 1000)
- run(on_request, on_notify, config.on_setup)
+ -- run(on_request, on_notify, nil, 1000)
+ run(on_request, on_notify, nil)
if config.on_exit then
config.on_exit(code, signal)
end
stop()
if config.test_name then
- exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
+ api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
end
end
diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua
index bb9cdb8390..6c6dec0667 100644
--- a/test/functional/plugin/lsp/utils_spec.lua
+++ b/test/functional/plugin/lsp/utils_spec.lua
@@ -1,12 +1,13 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local feed = helpers.feed
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
+local feed = n.feed
+local eq = t.eq
+local exec_lua = n.exec_lua
describe('vim.lsp.util', function()
- before_each(helpers.clear)
+ before_each(n.clear)
describe('stylize_markdown', function()
local stylize_markdown = function(content, opts)
@@ -142,7 +143,7 @@ describe('vim.lsp.util', function()
local screen
before_each(function()
- helpers.clear()
+ n.clear()
screen = Screen.new(80, 80)
screen:attach()
feed('79i<CR><Esc>') -- fill screen with empty lines
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 4826153edb..c95a96baca 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -1,36 +1,38 @@
-local helpers = require('test.functional.helpers')(after_each)
-local lsp_helpers = require('test.functional.plugin.lsp.helpers')
-
-local assert_log = helpers.assert_log
-local buf_lines = helpers.buf_lines
-local clear = helpers.clear
-local command = helpers.command
-local dedent = helpers.dedent
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local eval = helpers.eval
-local matches = helpers.matches
-local pcall_err = helpers.pcall_err
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local t_lsp = require('test.functional.plugin.lsp.testutil')
+
+local assert_log = t.assert_log
+local buf_lines = n.buf_lines
+local clear = n.clear
+local command = n.command
+local dedent = t.dedent
+local exec_lua = n.exec_lua
+local eq = t.eq
+local eval = n.eval
+local matches = t.matches
+local pcall_err = t.pcall_err
local pesc = vim.pesc
-local insert = helpers.insert
-local fn = helpers.fn
-local retry = helpers.retry
-local stop = helpers.stop
+local insert = n.insert
+local fn = n.fn
+local retry = t.retry
+local stop = n.stop
local NIL = vim.NIL
-local read_file = require('test.helpers').read_file
-local write_file = require('test.helpers').write_file
-local is_ci = helpers.is_ci
-local api = helpers.api
-local is_os = helpers.is_os
-local skip = helpers.skip
-local mkdir = helpers.mkdir
-local tmpname = helpers.tmpname
-
-local clear_notrace = lsp_helpers.clear_notrace
-local create_server_definition = lsp_helpers.create_server_definition
-local fake_lsp_code = lsp_helpers.fake_lsp_code
-local fake_lsp_logfile = lsp_helpers.fake_lsp_logfile
-local test_rpc_server = lsp_helpers.test_rpc_server
+local read_file = t.read_file
+local write_file = t.write_file
+local is_ci = t.is_ci
+local api = n.api
+local is_os = t.is_os
+local skip = t.skip
+local mkdir = t.mkdir
+local tmpname = t.tmpname
+
+local clear_notrace = t_lsp.clear_notrace
+local create_server_definition = t_lsp.create_server_definition
+local fake_lsp_code = t_lsp.fake_lsp_code
+local fake_lsp_logfile = t_lsp.fake_lsp_logfile
+local test_rpc_server = t_lsp.test_rpc_server
local function get_buf_option(name, bufnr)
bufnr = bufnr or 'BUFFER'
@@ -83,7 +85,7 @@ describe('LSP', function()
end)
after_each(function()
- exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
+ api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
-- exec_lua("lsp.stop_all_clients(true)")
end)
@@ -146,7 +148,7 @@ describe('LSP', function()
after_each(function()
stop()
exec_lua('lsp.stop_client(lsp.get_clients(), true)')
- exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
+ api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
end)
it('should run correctly', function()
@@ -249,7 +251,7 @@ describe('LSP', function()
if is_ci() then
pending('hangs the build on CI #14028, re-enable with freeze timeout #14204')
return
- elseif helpers.skip_fragile(pending) then
+ elseif t.skip_fragile(pending) then
return
end
local expected_handlers = {
@@ -279,7 +281,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'finish', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_finish',
on_setup = function()
@@ -312,7 +314,7 @@ describe('LSP', function()
end)
it('should fire autocommands on attach and detach', function()
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_init',
on_setup = function()
@@ -349,7 +351,7 @@ describe('LSP', function()
end)
it('should set default options on attach', function()
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
@@ -397,7 +399,7 @@ describe('LSP', function()
end)
it('should overwrite options set by ftplugins', function()
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
@@ -437,7 +439,7 @@ describe('LSP', function()
end)
it('should not overwrite user-defined options', function()
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
@@ -473,6 +475,12 @@ describe('LSP', function()
local server = _create_server()
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_current_buf(bufnr)
+ local detach_called = false
+ vim.api.nvim_create_autocmd("LspDetach", {
+ callback = function()
+ detach_called = true
+ end
+ })
local client_id = vim.lsp.start({ name = 'detach-dummy', cmd = server.cmd })
assert(client_id, "lsp.start must return client_id")
local client = vim.lsp.get_client_by_id(client_id)
@@ -484,11 +492,42 @@ describe('LSP', function()
client_id = client_id,
num_attached_before = num_attached_before,
num_attached_after = num_attached_after,
+ detach_called = detach_called,
}
]])
eq(true, result ~= nil, 'exec_lua must return result')
eq(1, result.num_attached_before)
eq(0, result.num_attached_after)
+ eq(true, result.detach_called)
+ end)
+
+ it('should not re-attach buffer if it was deleted in on_init #28575', function()
+ clear()
+ exec_lua(create_server_definition)
+ exec_lua([[
+ local server = _create_server({
+ handlers = {
+ initialize = function(method, params, callback)
+ vim.schedule(function()
+ callback(nil, { capabilities = {} })
+ end)
+ end
+ }
+ })
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local on_init_called = false
+ local client_id = vim.lsp.start({
+ name = 'detach-dummy',
+ cmd = server.cmd,
+ on_init = function()
+ vim.api.nvim_buf_delete(bufnr, {})
+ on_init_called = true
+ end
+ })
+ vim.lsp.buf_attach_client(bufnr, client_id)
+ local ok = vim.wait(1000, function() return on_init_called end)
+ assert(ok, "on_init was not called")
+ ]])
end)
it('client should return settings via workspace/configuration handler', function()
@@ -508,7 +547,7 @@ describe('LSP', function()
},
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_workspace_configuration',
on_init = function(_client)
@@ -598,7 +637,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'text_document_sync_save_bool',
on_init = function(c)
@@ -641,11 +680,11 @@ describe('LSP', function()
vim.lsp.stop_client(client_id)
return server.messages
]])
- eq(#messages, 4)
- eq(messages[1].method, 'initialize')
- eq(messages[2].method, 'initialized')
- eq(messages[3].method, 'shutdown')
- eq(messages[4].method, 'exit')
+ eq(4, #messages)
+ eq('initialize', messages[1].method)
+ eq('initialized', messages[2].method)
+ eq('shutdown', messages[3].method)
+ eq('exit', messages[4].method)
end)
it('BufWritePre sends willSave / willSaveWaitUntil, applies textEdits', function()
@@ -660,7 +699,7 @@ describe('LSP', function()
}
},
handlers = {
- ['textDocument/willSaveWaitUntil'] = function()
+ ['textDocument/willSaveWaitUntil'] = function(_, _, callback)
local text_edit = {
range = {
start = { line = 0, character = 0 },
@@ -668,7 +707,7 @@ describe('LSP', function()
},
newText = 'Hello'
}
- return { text_edit, }
+ callback(nil, { text_edit, })
end
},
})
@@ -692,7 +731,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server({
test_name = 'text_document_save_did_open',
on_init = function(c)
@@ -732,7 +771,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'text_document_sync_save_includeText',
on_init = function(c)
@@ -808,14 +847,12 @@ describe('LSP', function()
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
+ vim.cmd(BUFFER.."bwipeout")
]=])
end,
on_init = function(client)
client.stop()
exec_lua('vim.lsp.buf.type_definition()')
- exec_lua [[
- vim.api.nvim_command(BUFFER.."bwipeout")
- ]]
end,
on_exit = function(code, signal)
eq(0, code, 'exit code')
@@ -859,7 +896,7 @@ describe('LSP', function()
local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_forward_request_cancelled',
on_init = function(_client)
@@ -885,7 +922,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_forward_content_modified',
on_init = function(_client)
@@ -915,7 +952,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_pending_request_tracked',
on_init = function(_client)
@@ -949,7 +986,7 @@ describe('LSP', function()
local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_cancel_request_tracked',
on_init = function(_client)
@@ -982,7 +1019,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_tracked_requests_cleared',
on_init = function(_client)
@@ -1021,7 +1058,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'check_tracked_requests_cleared',
on_init = function(_client)
@@ -1057,7 +1094,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'finish', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_finish',
on_setup = function()
@@ -1067,12 +1104,10 @@ describe('LSP', function()
"testing";
"123";
})
- ]]
- eq(1, exec_lua('return TEST_RPC_CLIENT_ID'))
- eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
- eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
- exec_lua [[
- vim.api.nvim_command(BUFFER.."bwipeout")
+ assert(TEST_RPC_CLIENT_ID == 1)
+ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
+ assert(lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID))
+ vim.cmd(BUFFER.."bwipeout")
]]
end,
on_init = function(_client)
@@ -1101,7 +1136,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open',
on_setup = function()
@@ -1147,7 +1182,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open',
on_setup = function()
@@ -1190,7 +1225,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change',
on_setup = function()
@@ -1238,7 +1273,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change_noeol',
on_setup = function()
@@ -1305,7 +1340,7 @@ describe('LSP', function()
},
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'inlay_hint',
on_setup = function()
@@ -1332,7 +1367,7 @@ describe('LSP', function()
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
- vim.lsp.inlay_hint.enable(BUFFER)
+ vim.lsp.inlay_hint.enable(true, { bufnr = BUFFER })
]]
end
if ctx.method == 'textDocument/inlayHint' then
@@ -1352,7 +1387,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change_incremental',
options = {
@@ -1403,7 +1438,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change_incremental',
options = {
@@ -1457,7 +1492,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change_incremental_editing',
on_setup = function()
@@ -1485,7 +1520,7 @@ describe('LSP', function()
end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
- helpers.command('normal! 1Go')
+ n.command('normal! 1Go')
client.notify('finish')
end
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
@@ -1502,7 +1537,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change_multi',
on_setup = function()
@@ -1553,7 +1588,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_check_buffer_open_and_change_multi_and_close',
on_setup = function()
@@ -1607,7 +1642,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'finish', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'invalid_header',
on_setup = function() end,
@@ -1640,7 +1675,7 @@ describe('LSP', function()
},
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'decode_nil',
on_setup = function()
@@ -1807,7 +1842,7 @@ describe('LSP', function()
make_edit(1, 0, 2, 5, 'foobar'),
make_edit(4, 0, 5, 0, 'barfoo'),
}
- eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 1, {})'))
+ eq(true, api.nvim_buf_set_mark(1, 'a', 2, 1, {}))
exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
'First line of text',
@@ -1815,7 +1850,7 @@ describe('LSP', function()
'Fourth line of text',
'barfoo',
}, buf_lines(1))
- local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
+ local mark = api.nvim_buf_get_mark(1, 'a')
eq({ 2, 1 }, mark)
end)
@@ -1824,7 +1859,7 @@ describe('LSP', function()
make_edit(1, 0, 2, 15, 'foobar'),
make_edit(4, 0, 5, 0, 'barfoo'),
}
- eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 10, {})'))
+ eq(true, api.nvim_buf_set_mark(1, 'a', 2, 10, {}))
exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
'First line of text',
@@ -1832,7 +1867,7 @@ describe('LSP', function()
'Fourth line of text',
'barfoo',
}, buf_lines(1))
- local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
+ local mark = api.nvim_buf_get_mark(1, 'a')
eq({ 2, 9 }, mark)
end)
@@ -1841,19 +1876,19 @@ describe('LSP', function()
make_edit(1, 0, 4, 5, 'foobar'),
make_edit(4, 0, 5, 0, 'barfoo'),
}
- eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 4, 1, {})'))
+ eq(true, api.nvim_buf_set_mark(1, 'a', 4, 1, {}))
exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
'First line of text',
'foobaro',
}, buf_lines(1))
- local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
+ local mark = api.nvim_buf_get_mark(1, 'a')
eq({ 2, 1 }, mark)
end)
describe('cursor position', function()
it("don't fix the cursor if the range contains the cursor", function()
- fn.nvim_win_set_cursor(0, { 2, 6 })
+ api.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 19, 'Second line of text'),
}
@@ -1865,11 +1900,11 @@ describe('LSP', function()
'Fourth line of text',
'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 6 }, fn.nvim_win_get_cursor(0))
+ eq({ 2, 6 }, api.nvim_win_get_cursor(0))
end)
it('fix the cursor to the valid col if the content was removed', function()
- fn.nvim_win_set_cursor(0, { 2, 6 })
+ api.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 6, ''),
make_edit(1, 6, 1, 19, ''),
@@ -1882,11 +1917,11 @@ describe('LSP', function()
'Fourth line of text',
'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 0 }, fn.nvim_win_get_cursor(0))
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
end)
it('fix the cursor to the valid row if the content was removed', function()
- fn.nvim_win_set_cursor(0, { 2, 6 })
+ api.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 6, ''),
make_edit(0, 18, 5, 0, ''),
@@ -1895,11 +1930,11 @@ describe('LSP', function()
eq({
'First line of text',
}, buf_lines(1))
- eq({ 1, 17 }, fn.nvim_win_get_cursor(0))
+ eq({ 1, 17 }, api.nvim_win_get_cursor(0))
end)
it('fix the cursor row', function()
- fn.nvim_win_set_cursor(0, { 3, 0 })
+ api.nvim_win_set_cursor(0, { 3, 0 })
local edits = {
make_edit(1, 0, 2, 0, ''),
}
@@ -1910,14 +1945,14 @@ describe('LSP', function()
'Fourth line of text',
'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 0 }, fn.nvim_win_get_cursor(0))
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
end)
it('fix the cursor col', function()
-- append empty last line. See #22636
- exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, { '' })
+ api.nvim_buf_set_lines(1, -1, -1, true, { '' })
- fn.nvim_win_set_cursor(0, { 2, 11 })
+ api.nvim_win_set_cursor(0, { 2, 11 })
local edits = {
make_edit(1, 7, 1, 11, ''),
}
@@ -1930,11 +1965,11 @@ describe('LSP', function()
'å å ɧ 汉语 ↥ 🤦 🦄',
'',
}, buf_lines(1))
- eq({ 2, 7 }, fn.nvim_win_get_cursor(0))
+ eq({ 2, 7 }, api.nvim_win_get_cursor(0))
end)
it('fix the cursor row and col', function()
- fn.nvim_win_set_cursor(0, { 2, 12 })
+ api.nvim_win_set_cursor(0, { 2, 12 })
local edits = {
make_edit(0, 11, 1, 12, ''),
}
@@ -1945,7 +1980,7 @@ describe('LSP', function()
'Fourth line of text',
'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 1, 11 }, fn.nvim_win_get_cursor(0))
+ eq({ 1, 11 }, api.nvim_win_get_cursor(0))
end)
end)
@@ -2021,7 +2056,7 @@ describe('LSP', function()
end)
describe('apply_text_document_edit', function()
- local target_bufnr
+ local target_bufnr --- @type integer
local text_document_edit = function(editVersion)
return {
edits = {
@@ -2267,7 +2302,7 @@ describe('LSP', function()
},
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
end)
it(
'Supports file creation in folder that needs to be created with CreateFile payload',
@@ -2285,7 +2320,7 @@ describe('LSP', function()
},
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
end
)
it('createFile does not touch file if it exists and ignoreIfExists is set', function()
@@ -2304,7 +2339,7 @@ describe('LSP', function()
},
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
eq('Dummy content', read_file(tmpfile))
end)
it('createFile overrides file if overwrite is set', function()
@@ -2324,7 +2359,7 @@ describe('LSP', function()
},
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
eq('', read_file(tmpfile))
end)
it('DeleteFile delete file and buffer', function()
@@ -2348,8 +2383,8 @@ describe('LSP', function()
},
}
eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16'))
- eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
- eq(false, exec_lua('return vim.api.nvim_buf_is_loaded(vim.fn.bufadd(...))', tmpfile))
+ eq(false, vim.uv.fs_stat(tmpfile) ~= nil)
+ eq(false, api.nvim_buf_is_loaded(fn.bufadd(tmpfile)))
end)
it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function()
local tmpfile = tmpname()
@@ -2367,12 +2402,12 @@ describe('LSP', function()
},
}
eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit))
- eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ eq(false, vim.uv.fs_stat(tmpfile) ~= nil)
end)
end)
describe('lsp.util.rename', function()
- local pathsep = helpers.get_pathsep()
+ local pathsep = n.get_pathsep()
it('Can rename an existing file', function()
local old = tmpname()
@@ -2395,9 +2430,9 @@ describe('LSP', function()
new
)
eq({ 'Test content' }, lines)
- local exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', old)
+ local exists = vim.uv.fs_stat(old) ~= nil
eq(false, exists)
- exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', new)
+ exists = vim.uv.fs_stat(new) ~= nil
eq(true, exists)
os.remove(new)
end)
@@ -2408,7 +2443,7 @@ describe('LSP', function()
os.remove(old_dir)
os.remove(new_dir)
- helpers.mkdir_p(old_dir)
+ n.mkdir_p(old_dir)
local file = 'file.txt'
write_file(old_dir .. pathsep .. file, 'Test content')
@@ -2433,9 +2468,9 @@ describe('LSP', function()
file
)
eq({ 'Test content' }, lines)
- eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old_dir))
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir))
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir .. pathsep .. file))
+ eq(false, vim.uv.fs_stat(old_dir) ~= nil)
+ eq(true, vim.uv.fs_stat(new_dir) ~= nil)
+ eq(true, vim.uv.fs_stat(new_dir .. pathsep .. file) ~= nil)
os.remove(new_dir)
end)
@@ -2444,7 +2479,7 @@ describe('LSP', function()
local new = tmpname()
os.remove(old)
os.remove(new)
- helpers.mkdir_p(old)
+ n.mkdir_p(old)
local result = exec_lua(
[[
@@ -2499,7 +2534,7 @@ describe('LSP', function()
new
)
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq(true, vim.uv.fs_stat(old) ~= nil)
eq('New file', read_file(new))
exec_lua(
@@ -2513,7 +2548,7 @@ describe('LSP', function()
new
)
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq(true, vim.uv.fs_stat(old) ~= nil)
eq('New file', read_file(new))
end
)
@@ -2543,8 +2578,8 @@ describe('LSP', function()
old,
new
)
- eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(false, vim.uv.fs_stat(old) ~= nil)
+ eq(true, vim.uv.fs_stat(new) ~= nil)
eq(true, undo_kept)
end)
it('Maintains undo information for unloaded buffer', function()
@@ -2570,8 +2605,8 @@ describe('LSP', function()
old,
new
)
- eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(false, vim.uv.fs_stat(old) ~= nil)
+ eq(true, vim.uv.fs_stat(new) ~= nil)
eq(true, undo_kept)
end)
it('Does not rename file when it conflicts with a buffer without file', function()
@@ -2615,8 +2650,8 @@ describe('LSP', function()
new
)
- eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(false, vim.uv.fs_stat(old) ~= nil)
+ eq(true, vim.uv.fs_stat(new) ~= nil)
eq('Old file', read_file(new))
end)
end)
@@ -2697,6 +2732,7 @@ describe('LSP', function()
eq(expected, actual)
end)
end)
+
describe('lsp.util.symbols_to_items', function()
describe('convert DocumentSymbol[] to items', function()
it('DocumentSymbol has children', function()
@@ -2971,7 +3007,7 @@ describe('LSP', function()
end)
describe('lsp.util.jump_to_location', function()
- local target_bufnr
+ local target_bufnr --- @type integer
before_each(function()
target_bufnr = exec_lua [[
@@ -2994,10 +3030,10 @@ describe('LSP', function()
local jump = function(msg)
eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, 'utf-16'))
- eq(target_bufnr, exec_lua [[return vim.fn.bufnr('%')]])
+ eq(target_bufnr, fn.bufnr('%'))
return {
- line = exec_lua [[return vim.fn.line('.')]],
- col = exec_lua [[return vim.fn.col('.')]],
+ line = fn.line('.'),
+ col = fn.col('.'),
}
end
@@ -3027,25 +3063,25 @@ describe('LSP', function()
local pos = jump(location(1, 2, 1, 2))
eq(2, pos.line)
eq(4, pos.col)
- eq('å', exec_lua [[return vim.fn.expand('<cword>')]])
+ eq('å', fn.expand('<cword>'))
end)
it('adds current position to jumplist before jumping', function()
- fn.nvim_win_set_buf(0, target_bufnr)
- local mark = fn.nvim_buf_get_mark(target_bufnr, "'")
+ api.nvim_win_set_buf(0, target_bufnr)
+ local mark = api.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
- fn.nvim_win_set_cursor(0, { 2, 3 })
+ api.nvim_win_set_cursor(0, { 2, 3 })
jump(location(0, 9, 0, 9))
- mark = fn.nvim_buf_get_mark(target_bufnr, "'")
+ mark = api.nvim_buf_get_mark(target_bufnr, "'")
eq({ 2, 3 }, mark)
end)
end)
describe('lsp.util.show_document', function()
- local target_bufnr
- local target_bufnr2
+ local target_bufnr --- @type integer
+ local target_bufnr2 --- @type integer
before_each(function()
target_bufnr = exec_lua([[
@@ -3084,11 +3120,11 @@ describe('LSP', function()
)
)
if focus == true or focus == nil then
- eq(target_bufnr, exec_lua([[return vim.fn.bufnr('%')]]))
+ eq(target_bufnr, fn.bufnr('%'))
end
return {
- line = exec_lua([[return vim.fn.line('.')]]),
- col = exec_lua([[return vim.fn.col('.')]]),
+ line = fn.line('.'),
+ col = fn.col('.'),
}
end
@@ -3132,101 +3168,101 @@ describe('LSP', function()
end)
it('does not add current position to jumplist if not focus', function()
- fn.nvim_win_set_buf(0, target_bufnr)
- local mark = fn.nvim_buf_get_mark(target_bufnr, "'")
+ api.nvim_win_set_buf(0, target_bufnr)
+ local mark = api.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
- fn.nvim_win_set_cursor(0, { 2, 3 })
+ api.nvim_win_set_cursor(0, { 2, 3 })
show_document(location(0, 9, 0, 9), false, true)
show_document(location(0, 9, 0, 9, true), false, true)
- mark = fn.nvim_buf_get_mark(target_bufnr, "'")
+ mark = api.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
end)
it('does not change cursor position if not focus and not reuse_win', function()
- fn.nvim_win_set_buf(0, target_bufnr)
- local cursor = fn.nvim_win_get_cursor(0)
+ api.nvim_win_set_buf(0, target_bufnr)
+ local cursor = api.nvim_win_get_cursor(0)
show_document(location(0, 9, 0, 9), false, false)
- eq(cursor, fn.nvim_win_get_cursor(0))
+ eq(cursor, api.nvim_win_get_cursor(0))
end)
it('does not change window if not focus', function()
- fn.nvim_win_set_buf(0, target_bufnr)
- local win = fn.nvim_get_current_win()
+ api.nvim_win_set_buf(0, target_bufnr)
+ local win = api.nvim_get_current_win()
-- same document/bufnr
show_document(location(0, 9, 0, 9), false, true)
- eq(win, fn.nvim_get_current_win())
+ eq(win, api.nvim_get_current_win())
-- different document/bufnr, new window/split
show_document(location(0, 9, 0, 9, true), false, true)
- eq(2, #fn.nvim_list_wins())
- eq(win, fn.nvim_get_current_win())
+ eq(2, #api.nvim_list_wins())
+ eq(win, api.nvim_get_current_win())
end)
it("respects 'reuse_win' parameter", function()
- fn.nvim_win_set_buf(0, target_bufnr)
+ api.nvim_win_set_buf(0, target_bufnr)
-- does not create a new window if the buffer is already open
show_document(location(0, 9, 0, 9), false, true)
- eq(1, #fn.nvim_list_wins())
+ eq(1, #api.nvim_list_wins())
-- creates a new window even if the buffer is already open
show_document(location(0, 9, 0, 9), false, false)
- eq(2, #fn.nvim_list_wins())
+ eq(2, #api.nvim_list_wins())
end)
it('correctly sets the cursor of the split if range is given without focus', function()
- fn.nvim_win_set_buf(0, target_bufnr)
+ api.nvim_win_set_buf(0, target_bufnr)
show_document(location(0, 9, 0, 9, true), false, true)
- local wins = fn.nvim_list_wins()
+ local wins = api.nvim_list_wins()
eq(2, #wins)
table.sort(wins)
- eq({ 1, 0 }, fn.nvim_win_get_cursor(wins[1]))
- eq({ 1, 9 }, fn.nvim_win_get_cursor(wins[2]))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(wins[1]))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(wins[2]))
end)
it('does not change cursor of the split if not range and not focus', function()
- fn.nvim_win_set_buf(0, target_bufnr)
- fn.nvim_win_set_cursor(0, { 2, 3 })
+ api.nvim_win_set_buf(0, target_bufnr)
+ api.nvim_win_set_cursor(0, { 2, 3 })
exec_lua([[vim.cmd.new()]])
- fn.nvim_win_set_buf(0, target_bufnr2)
- fn.nvim_win_set_cursor(0, { 2, 3 })
+ api.nvim_win_set_buf(0, target_bufnr2)
+ api.nvim_win_set_cursor(0, { 2, 3 })
show_document({ uri = 'file:///fake/uri2' }, false, true)
- local wins = fn.nvim_list_wins()
+ local wins = api.nvim_list_wins()
eq(2, #wins)
- eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[1]))
- eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[2]))
+ eq({ 2, 3 }, api.nvim_win_get_cursor(wins[1]))
+ eq({ 2, 3 }, api.nvim_win_get_cursor(wins[2]))
end)
it('respects existing buffers', function()
- fn.nvim_win_set_buf(0, target_bufnr)
- local win = fn.nvim_get_current_win()
+ api.nvim_win_set_buf(0, target_bufnr)
+ local win = api.nvim_get_current_win()
exec_lua([[vim.cmd.new()]])
- fn.nvim_win_set_buf(0, target_bufnr2)
- fn.nvim_win_set_cursor(0, { 2, 3 })
- local split = fn.nvim_get_current_win()
+ api.nvim_win_set_buf(0, target_bufnr2)
+ api.nvim_win_set_cursor(0, { 2, 3 })
+ local split = api.nvim_get_current_win()
-- reuse win for open document/bufnr if called from split
show_document(location(0, 9, 0, 9, true), false, true)
- eq({ 1, 9 }, fn.nvim_win_get_cursor(split))
- eq(2, #fn.nvim_list_wins())
+ eq({ 1, 9 }, api.nvim_win_get_cursor(split))
+ eq(2, #api.nvim_list_wins())
- fn.nvim_set_current_win(win)
+ api.nvim_set_current_win(win)
-- reuse win for open document/bufnr if called outside the split
show_document(location(0, 9, 0, 9, true), false, true)
- eq({ 1, 9 }, fn.nvim_win_get_cursor(split))
- eq(2, #fn.nvim_list_wins())
+ eq({ 1, 9 }, api.nvim_win_get_cursor(split))
+ eq(2, #api.nvim_list_wins())
end)
end)
@@ -3464,6 +3500,442 @@ describe('LSP', function()
end)
end)
+ describe('vim.lsp.buf.typehierarchy subtypes', function()
+ it('does nothing for an empty response', function()
+ local qflist_count = exec_lua([=[
+ require'vim.lsp.handlers'['typeHierarchy/subtypes'](nil, nil, {})
+ return #vim.fn.getqflist()
+ ]=])
+ eq(0, qflist_count)
+ end)
+
+ it('opens the quickfix list with the right subtypes', function()
+ clear()
+ exec_lua(create_server_definition)
+ local qflist = exec_lua([=[
+ local clangd_response = { {
+ data = {
+ parents = { {
+ parents = { {
+ parents = { {
+ parents = {},
+ symbolID = "62B3D268A01B9978"
+ } },
+ symbolID = "DC9B0AD433B43BEC"
+ } },
+ symbolID = "06B5F6A19BA9F6A8"
+ } },
+ symbolID = "EDC336589C09ABB2"
+ },
+ kind = 5,
+ name = "D2",
+ range = {
+ ["end"] = {
+ character = 8,
+ line = 9
+ },
+ start = {
+ character = 6,
+ line = 9
+ }
+ },
+ selectionRange = {
+ ["end"] = {
+ character = 8,
+ line = 9
+ },
+ start = {
+ character = 6,
+ line = 9
+ }
+ },
+ uri = "file:///home/jiangyinzuo/hello.cpp"
+ }, {
+ data = {
+ parents = { {
+ parents = { {
+ parents = { {
+ parents = {},
+ symbolID = "62B3D268A01B9978"
+ } },
+ symbolID = "DC9B0AD433B43BEC"
+ } },
+ symbolID = "06B5F6A19BA9F6A8"
+ } },
+ symbolID = "AFFCAED15557EF08"
+ },
+ kind = 5,
+ name = "D1",
+ range = {
+ ["end"] = {
+ character = 8,
+ line = 8
+ },
+ start = {
+ character = 6,
+ line = 8
+ }
+ },
+ selectionRange = {
+ ["end"] = {
+ character = 8,
+ line = 8
+ },
+ start = {
+ character = 6,
+ line = 8
+ }
+ },
+ uri = "file:///home/jiangyinzuo/hello.cpp"
+ } }
+
+ local server = _create_server({
+ capabilities = {
+ positionEncoding = "utf-8"
+ },
+ })
+ local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ local handler = require'vim.lsp.handlers'['typeHierarchy/subtypes']
+ handler(nil, clangd_response, { client_id = client_id, bufnr = 1 })
+ return vim.fn.getqflist()
+ ]=])
+
+ local expected = {
+ {
+ bufnr = 2,
+ col = 7,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 10,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'D2',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ {
+ bufnr = 2,
+ col = 7,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 9,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'D1',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
+
+ eq(expected, qflist)
+ end)
+
+ it('opens the quickfix list with the right subtypes and details', function()
+ clear()
+ exec_lua(create_server_definition)
+ local qflist = exec_lua([=[
+ local jdtls_response = {
+ {
+ data = { element = '=hello-java_ed323c3c/_<{Main.java[Main[A' },
+ detail = '',
+ kind = 5,
+ name = 'A',
+ range = {
+ ['end'] = { character = 26, line = 3 },
+ start = { character = 1, line = 3 },
+ },
+ selectionRange = {
+ ['end'] = { character = 8, line = 3 },
+ start = { character = 7, line = 3 },
+ },
+ tags = {},
+ uri = 'file:///home/jiangyinzuo/hello-java/Main.java',
+ },
+ {
+ data = { element = '=hello-java_ed323c3c/_<mylist{MyList.java[MyList[Inner' },
+ detail = 'mylist',
+ kind = 5,
+ name = 'MyList$Inner',
+ range = {
+ ['end'] = { character = 37, line = 3 },
+ start = { character = 1, line = 3 },
+ },
+ selectionRange = {
+ ['end'] = { character = 19, line = 3 },
+ start = { character = 14, line = 3 },
+ },
+ tags = {},
+ uri = 'file:///home/jiangyinzuo/hello-java/mylist/MyList.java',
+ },
+ }
+
+ local server = _create_server({
+ capabilities = {
+ positionEncoding = "utf-8"
+ },
+ })
+ local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ local handler = require'vim.lsp.handlers'['typeHierarchy/subtypes']
+ handler(nil, jdtls_response, { client_id = client_id, bufnr = 1 })
+ return vim.fn.getqflist()
+ ]=])
+
+ local expected = {
+ {
+ bufnr = 2,
+ col = 2,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 4,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'A',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ {
+ bufnr = 3,
+ col = 2,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 4,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'MyList$Inner mylist',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
+ eq(expected, qflist)
+ end)
+ end)
+
+ describe('vim.lsp.buf.typehierarchy supertypes', function()
+ it('does nothing for an empty response', function()
+ local qflist_count = exec_lua([=[
+ require'vim.lsp.handlers'['typeHierarchy/supertypes'](nil, nil, {})
+ return #vim.fn.getqflist()
+ ]=])
+ eq(0, qflist_count)
+ end)
+
+ it('opens the quickfix list with the right supertypes', function()
+ clear()
+ exec_lua(create_server_definition)
+ local qflist = exec_lua([=[
+ local clangd_response = { {
+ data = {
+ parents = { {
+ parents = { {
+ parents = { {
+ parents = {},
+ symbolID = "62B3D268A01B9978"
+ } },
+ symbolID = "DC9B0AD433B43BEC"
+ } },
+ symbolID = "06B5F6A19BA9F6A8"
+ } },
+ symbolID = "EDC336589C09ABB2"
+ },
+ kind = 5,
+ name = "D2",
+ range = {
+ ["end"] = {
+ character = 8,
+ line = 9
+ },
+ start = {
+ character = 6,
+ line = 9
+ }
+ },
+ selectionRange = {
+ ["end"] = {
+ character = 8,
+ line = 9
+ },
+ start = {
+ character = 6,
+ line = 9
+ }
+ },
+ uri = "file:///home/jiangyinzuo/hello.cpp"
+ }, {
+ data = {
+ parents = { {
+ parents = { {
+ parents = { {
+ parents = {},
+ symbolID = "62B3D268A01B9978"
+ } },
+ symbolID = "DC9B0AD433B43BEC"
+ } },
+ symbolID = "06B5F6A19BA9F6A8"
+ } },
+ symbolID = "AFFCAED15557EF08"
+ },
+ kind = 5,
+ name = "D1",
+ range = {
+ ["end"] = {
+ character = 8,
+ line = 8
+ },
+ start = {
+ character = 6,
+ line = 8
+ }
+ },
+ selectionRange = {
+ ["end"] = {
+ character = 8,
+ line = 8
+ },
+ start = {
+ character = 6,
+ line = 8
+ }
+ },
+ uri = "file:///home/jiangyinzuo/hello.cpp"
+ } }
+
+ local server = _create_server({
+ capabilities = {
+ positionEncoding = "utf-8"
+ },
+ })
+ local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ local handler = require'vim.lsp.handlers'['typeHierarchy/supertypes']
+ handler(nil, clangd_response, { client_id = client_id, bufnr = 1 })
+ return vim.fn.getqflist()
+ ]=])
+
+ local expected = {
+ {
+ bufnr = 2,
+ col = 7,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 10,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'D2',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ {
+ bufnr = 2,
+ col = 7,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 9,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'D1',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
+
+ eq(expected, qflist)
+ end)
+
+ it('opens the quickfix list with the right supertypes and details', function()
+ clear()
+ exec_lua(create_server_definition)
+ local qflist = exec_lua([=[
+ local jdtls_response = {
+ {
+ data = { element = '=hello-java_ed323c3c/_<{Main.java[Main[A' },
+ detail = '',
+ kind = 5,
+ name = 'A',
+ range = {
+ ['end'] = { character = 26, line = 3 },
+ start = { character = 1, line = 3 },
+ },
+ selectionRange = {
+ ['end'] = { character = 8, line = 3 },
+ start = { character = 7, line = 3 },
+ },
+ tags = {},
+ uri = 'file:///home/jiangyinzuo/hello-java/Main.java',
+ },
+ {
+ data = { element = '=hello-java_ed323c3c/_<mylist{MyList.java[MyList[Inner' },
+ detail = 'mylist',
+ kind = 5,
+ name = 'MyList$Inner',
+ range = {
+ ['end'] = { character = 37, line = 3 },
+ start = { character = 1, line = 3 },
+ },
+ selectionRange = {
+ ['end'] = { character = 19, line = 3 },
+ start = { character = 14, line = 3 },
+ },
+ tags = {},
+ uri = 'file:///home/jiangyinzuo/hello-java/mylist/MyList.java',
+ },
+ }
+
+ local server = _create_server({
+ capabilities = {
+ positionEncoding = "utf-8"
+ },
+ })
+ local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ local handler = require'vim.lsp.handlers'['typeHierarchy/supertypes']
+ handler(nil, jdtls_response, { client_id = client_id, bufnr = 1 })
+ return vim.fn.getqflist()
+ ]=])
+
+ local expected = {
+ {
+ bufnr = 2,
+ col = 2,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 4,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'A',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ {
+ bufnr = 3,
+ col = 2,
+ end_col = 0,
+ end_lnum = 0,
+ lnum = 4,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'MyList$Inner mylist',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
+ eq(expected, qflist)
+ end)
+ end)
+
describe('vim.lsp.buf.rename', function()
for _, test in ipairs({
{
@@ -3504,7 +3976,7 @@ describe('LSP', function()
},
}) do
it(test.it, function()
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = test.name,
on_init = function(_client)
@@ -3554,7 +4026,7 @@ describe('LSP', function()
describe('vim.lsp.buf.code_action', function()
it('Calls client side command if available', function()
- local client
+ local client --- @type vim.lsp.Client
local expected_handlers = {
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
@@ -3592,7 +4064,7 @@ describe('LSP', function()
}
end)
it('Calls workspace/executeCommand if no client side command', function()
- local client
+ local client --- @type vim.lsp.Client
local expected_handlers = {
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{
@@ -3632,7 +4104,7 @@ describe('LSP', function()
})
end)
it('Filters and automatically applies action if requested', function()
- local client
+ local client --- @type vim.lsp.Client
local expected_handlers = {
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
@@ -3701,8 +4173,8 @@ describe('LSP', function()
}
},
handlers = {
- ["textDocument/codeAction"] = function()
- return {
+ ["textDocument/codeAction"] = function(_, _, callback)
+ callback(nil, {
{
title = "Code Action 1",
command = {
@@ -3710,10 +4182,10 @@ describe('LSP', function()
command = "command:1",
}
}
- }
+ })
end,
- ["codeAction/resolve"] = function()
- return nil, "resolve failed"
+ ["codeAction/resolve"] = function(_, _, callback)
+ callback("resolve failed", nil)
end,
}
})
@@ -3732,6 +4204,7 @@ describe('LSP', function()
eq('command:1', result[5].params.command)
end)
end)
+
describe('vim.lsp.commands', function()
it('Accepts only string keys', function()
matches(
@@ -3746,9 +4219,10 @@ describe('LSP', function()
)
end)
end)
+
describe('vim.lsp.codelens', function()
it('uses client commands', function()
- local client
+ local client --- @type vim.lsp.Client
local expected_handlers = {
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
@@ -3802,7 +4276,7 @@ describe('LSP', function()
end)
it('releases buffer refresh lock', function()
- local client
+ local client --- @type vim.lsp.Client
local expected_handlers = {
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
@@ -3879,11 +4353,97 @@ describe('LSP', function()
end,
}
end)
+
+ it('refresh multiple buffers', function()
+ local lens_title_per_fake_uri = {
+ ['file:///fake/uri1'] = 'Lens1',
+ ['file:///fake/uri2'] = 'Lens2',
+ }
+ clear()
+ exec_lua(create_server_definition)
+
+ -- setup lsp
+ exec_lua(
+ [[
+ local lens_title_per_fake_uri = ...
+ local server = _create_server({
+ capabilities = {
+ codeLensProvider = {
+ resolveProvider = true
+ },
+ },
+ handlers = {
+ ["textDocument/codeLens"] = function(method, params, callback)
+ local lenses = {
+ {
+ range = {
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 0, character = 0 },
+ },
+ command = {
+ title = lens_title_per_fake_uri[params.textDocument.uri],
+ command = 'Dummy',
+ },
+ },
+ }
+ callback(nil, lenses)
+ end,
+ }
+ })
+
+ CLIENT_ID = vim.lsp.start({
+ name = "dummy",
+ cmd = server.cmd,
+ })
+ ]],
+ lens_title_per_fake_uri
+ )
+
+ -- create buffers and setup handler
+ exec_lua(
+ [[
+ local lens_title_per_fake_uri = ...
+ local default_buf = vim.api.nvim_get_current_buf()
+ for fake_uri, _ in pairs(lens_title_per_fake_uri) do
+ local bufnr = vim.uri_to_bufnr(fake_uri)
+ vim.api.nvim_set_current_buf(bufnr)
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'Some contents'})
+ vim.lsp.buf_attach_client(bufnr, CLIENT_ID)
+ end
+ vim.api.nvim_buf_delete(default_buf, {force = true})
+
+ REQUEST_COUNT = vim.tbl_count(lens_title_per_fake_uri)
+ RESPONSES = {}
+ local on_codelens = vim.lsp.codelens.on_codelens
+ vim.lsp.codelens.on_codelens = function (err, result, ctx, ...)
+ table.insert(RESPONSES, { err = err, result = result, ctx = ctx })
+ return on_codelens(err, result, ctx, ...)
+ end
+ ]],
+ lens_title_per_fake_uri
+ )
+
+ -- call codelens refresh
+ local cmds = exec_lua([[
+ RESPONSES = {}
+ vim.lsp.codelens.refresh()
+ vim.wait(100, function () return #RESPONSES >= REQUEST_COUNT end)
+
+ local cmds = {}
+ for _, resp in ipairs(RESPONSES) do
+ local uri = resp.ctx.params.textDocument.uri
+ cmds[uri] = resp.result[1].command
+ end
+ return cmds
+ ]])
+ eq({ command = 'Dummy', title = 'Lens1' }, cmds['file:///fake/uri1'])
+ eq({ command = 'Dummy', title = 'Lens2' }, cmds['file:///fake/uri2'])
+ end)
end)
describe('vim.lsp.buf.format', function()
it('Aborts with notify if no client matches filter', function()
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_init',
on_init = function(c)
@@ -3912,7 +4472,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_formatting',
on_init = function(c)
@@ -3945,7 +4505,7 @@ describe('LSP', function()
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
{ NIL, {}, { method = 'start', client_id = 1 } },
}
- local client
+ local client --- @type vim.lsp.Client
test_rpc_server {
test_name = 'basic_formatting',
on_init = function(c)
@@ -4068,6 +4628,9 @@ describe('LSP', function()
end
]])
local fail_msg = '[LSP] Format request failed, no matching language servers.'
+ --- @param name string
+ --- @param formatting boolean
+ --- @param range_formatting boolean
local function check_notify(name, formatting, range_formatting)
local timeout_msg = '[LSP][' .. name .. '] timeout'
exec_lua(
@@ -4131,13 +4694,13 @@ describe('LSP', function()
},
handlers = {
---@return lsp.Location[]
- ['textDocument/definition'] = function()
- return { _G.mock_locations[1] }
+ ['textDocument/definition'] = function(_, _, callback)
+ callback(nil, { _G.mock_locations[1] })
end,
---@return lsp.WorkspaceSymbol[]
- ['workspace/symbol'] = function(_, request)
+ ['workspace/symbol'] = function(_, request, callback)
assert(request.query == 'foobar')
- return {
+ callback(nil, {
{
name = 'foobar',
kind = 13, ---@type lsp.SymbolKind
@@ -4148,7 +4711,7 @@ describe('LSP', function()
kind = 12, ---@type lsp.SymbolKind
location = _G.mock_locations[2],
}
- }
+ })
end,
},
})
@@ -4221,10 +4784,10 @@ describe('LSP', function()
server:shutdown()
return vim.json.decode(init)
]]
- eq(result.method, 'initialize')
+ eq('initialize', result.method)
end)
- it('can connect to lsp server via rpc.domain_socket_connect', function()
- local tmpfile
+ it('can connect to lsp server via pipe or domain_socket', function()
+ local tmpfile --- @type string
if is_os('win') then
tmpfile = '\\\\.\\\\pipe\\pipe.test'
else
@@ -4248,7 +4811,7 @@ describe('LSP', function()
client:close()
end))
end)
- vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.domain_socket_connect(SOCK) })
+ vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.connect(SOCK) })
vim.wait(1000, function() return init ~= nil end)
assert(init, "server must receive `initialize` request")
server:close()
@@ -4257,7 +4820,7 @@ describe('LSP', function()
]],
tmpfile
)
- eq(result.method, 'initialize')
+ eq('initialize', result.method)
end)
end)
@@ -4449,18 +5012,26 @@ describe('LSP', function()
string.format('sends notifications when files change (watchfunc=%s)', watchfunc),
function()
if watchfunc == 'fswatch' then
+ skip(is_os('win'), 'not supported on windows')
+ skip(is_os('mac'), 'flaky test on mac')
skip(
not is_ci() and fn.executable('fswatch') == 0,
'fswatch not installed and not on CI'
)
- skip(is_os('win'), 'not supported on windows')
- skip(is_os('mac'), 'flaky')
end
- skip(
- is_os('bsd'),
- 'kqueue only reports events on watched folder itself, not contained files #26110'
- )
+ if watchfunc == 'watch' then
+ skip(is_os('mac'), 'flaky test on mac')
+ skip(
+ is_os('bsd'),
+ 'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38'
+ )
+ else
+ skip(
+ is_os('bsd'),
+ 'kqueue only reports events on watched folder itself, not contained files #26110'
+ )
+ end
local root_dir = tmpname()
os.remove(root_dir)
@@ -4679,14 +5250,7 @@ describe('LSP', function()
)
local function watched_uri(fname)
- return exec_lua(
- [[
- local root_dir, fname = ...
- return vim.uri_from_fname(root_dir .. '/' .. fname)
- ]],
- root_dir,
- fname
- )
+ return vim.uri_from_fname(root_dir .. '/' .. fname)
end
eq(4, #result)
@@ -4792,13 +5356,7 @@ describe('LSP', function()
)
local function watched_uri(fname)
- return exec_lua(
- [[
- local fname = ...
- return vim.uri_from_fname('/dir/' .. fname)
- ]],
- fname
- )
+ return vim.uri_from_fname('/dir/' .. fname)
end
eq(3, #result)
@@ -4923,30 +5481,21 @@ describe('LSP', function()
root_dir
)
- local function watched_uri(fname)
- return exec_lua(
- [[
- return vim.uri_from_fname(...)
- ]],
- fname
- )
- end
-
eq(3, #result)
eq('workspace/didChangeWatchedFiles', result[3].method)
eq({
changes = {
{
type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]),
- uri = watched_uri('file1'),
+ uri = vim.uri_from_fname('file1'),
},
{
type = exec_lua([[return vim.lsp.protocol.FileChangeType.Changed]]),
- uri = watched_uri('file1'),
+ uri = vim.uri_from_fname('file1'),
},
{
type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]),
- uri = watched_uri('file2'),
+ uri = vim.uri_from_fname('file2'),
},
},
}, result[3].params)
@@ -5009,7 +5558,7 @@ describe('LSP', function()
)
end
- eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
+ eq(is_os('mac') or is_os('win'), check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
eq(false, check_registered(vim.empty_dict()))
eq(
false,
diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua
index 5bfa566729..978178191c 100644
--- a/test/functional/plugin/man_spec.lua
+++ b/test/functional/plugin/man_spec.lua
@@ -1,17 +1,19 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local command, rawfeed = helpers.command, helpers.rawfeed
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local fn = helpers.fn
-local nvim_prog = helpers.nvim_prog
-local matches = helpers.matches
-local write_file = helpers.write_file
-local tmpname = helpers.tmpname
-local eq = helpers.eq
+
+local command, feed = n.command, n.feed
+local clear = n.clear
+local exec_lua = n.exec_lua
+local fn = n.fn
+local nvim_prog = n.nvim_prog
+local matches = t.matches
+local write_file = t.write_file
+local tmpname = t.tmpname
+local eq = t.eq
local pesc = vim.pesc
-local skip = helpers.skip
-local is_ci = helpers.is_ci
+local skip = t.skip
+local is_ci = t.is_ci
-- Collects all names passed to find_path() after attempting ":Man foo".
local function get_search_history(name)
@@ -44,7 +46,7 @@ describe(':Man', function()
end)
describe('man.lua: highlight_line()', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
command('syntax on')
@@ -64,7 +66,7 @@ describe(':Man', function()
end)
it('clears backspaces from text and adds highlights', function()
- rawfeed(
+ feed(
[[
ithis i<C-v><C-h>is<C-v><C-h>s a<C-v><C-h>a test
with _<C-v><C-h>o_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>c_<C-v><C-h>k text<ESC>]]
@@ -90,7 +92,7 @@ describe(':Man', function()
end)
it('clears escape sequences from text and adds highlights', function()
- rawfeed(
+ feed(
[[
ithis <C-v><ESC>[1mis <C-v><ESC>[3ma <C-v><ESC>[4mtest<C-v><ESC>[0m
<C-v><ESC>[4mwith<C-v><ESC>[24m <C-v><ESC>[4mescaped<C-v><ESC>[24m <C-v><ESC>[4mtext<C-v><ESC>[24m<ESC>]]
@@ -116,7 +118,7 @@ describe(':Man', function()
end)
it('highlights multibyte text', function()
- rawfeed(
+ feed(
[[
ithis i<C-v><C-h>is<C-v><C-h>s あ<C-v><C-h>あ test
with _<C-v><C-h>ö_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>̃_<C-v><C-h>c_<C-v><C-h>k te<C-v><ESC>[3mxt¶<C-v><ESC>[0m<ESC>]]
@@ -132,7 +134,7 @@ describe(':Man', function()
end)
it('highlights underscores based on context', function()
- rawfeed(
+ feed(
[[
i_<C-v><C-h>_b<C-v><C-h>be<C-v><C-h>eg<C-v><C-h>gi<C-v><C-h>in<C-v><C-h>ns<C-v><C-h>s
m<C-v><C-h>mi<C-v><C-h>id<C-v><C-h>d_<C-v><C-h>_d<C-v><C-h>dl<C-v><C-h>le<C-v><C-h>e
@@ -150,7 +152,7 @@ describe(':Man', function()
end)
it('highlights various bullet formats', function()
- rawfeed([[
+ feed([[
i· ·<C-v><C-h>·
+<C-v><C-h>o
+<C-v><C-h>+<C-v><C-h>o<C-v><C-h>o double<ESC>]])
@@ -166,7 +168,7 @@ describe(':Man', function()
end)
it('handles : characters in input', function()
- rawfeed([[
+ feed([[
i<C-v><C-[>[40m 0 <C-v><C-[>[41m 1 <C-v><C-[>[42m 2 <C-v><C-[>[43m 3
<C-v><C-[>[44m 4 <C-v><C-[>[45m 5 <C-v><C-[>[46m 6 <C-v><C-[>[47m 7 <C-v><C-[>[100m 8 <C-v><C-[>[101m 9
<C-v><C-[>[102m 10 <C-v><C-[>[103m 11 <C-v><C-[>[104m 12 <C-v><C-[>[105m 13 <C-v><C-[>[106m 14 <C-v><C-[>[107m 15
@@ -190,6 +192,7 @@ describe(':Man', function()
'--headless',
'+autocmd VimLeave * echo "quit works!!"',
'+Man!',
+ '+tag ls',
'+call nvim_input("q")',
}
matches('quit works!!', fn.system(args, { 'manpage contents' }))
diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua
index 530afd16e4..ae718ac1bd 100644
--- a/test/functional/plugin/matchparen_spec.lua
+++ b/test/functional/plugin/matchparen_spec.lua
@@ -1,14 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local clear = helpers.clear
-local command = helpers.command
-local api = helpers.api
-local feed = helpers.feed
-local eq = helpers.eq
+local clear = n.clear
+local command = n.command
+local api = n.api
+local feed = n.feed
+local eq = t.eq
describe('matchparen', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
clear { args = { '-u', 'NORC' } }
diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua
index 8511e6c703..1d5d20ec02 100644
--- a/test/functional/plugin/msgpack_spec.lua
+++ b/test/functional/plugin/msgpack_spec.lua
@@ -1,11 +1,13 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local api = helpers.api
-local eq = helpers.eq
-local nvim_eval = helpers.eval
-local nvim_command = helpers.command
-local exc_exec = helpers.exc_exec
-local ok = helpers.ok
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local api = n.api
+local eq = t.eq
+local nvim_eval = n.eval
+local nvim_command = n.command
+local exc_exec = n.exc_exec
+local ok = t.ok
local NIL = vim.NIL
describe('autoload/msgpack.vim', function()
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index 1c20548321..1c2bcbd497 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -1,13 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local clear = helpers.clear
+local t_shada = require('test.functional.shada.testutil')
+
+local clear = n.clear
local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed =
- helpers.eq, helpers.api, helpers.eval, helpers.command, helpers.exc_exec, helpers.fn, helpers.feed
-local neq = helpers.neq
-local read_file = helpers.read_file
+ t.eq, n.api, n.eval, n.command, n.exc_exec, n.fn, n.feed
+local neq = t.neq
+local read_file = t.read_file
-local shada_helpers = require('test.functional.shada.helpers')
-local get_shada_rw = shada_helpers.get_shada_rw
+local get_shada_rw = t_shada.get_shada_rw
local function reset(shada_file)
clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } }
@@ -2612,7 +2614,7 @@ end)
describe('plugin/shada.vim', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
- local eol = helpers.is_os('win') and '\r\n' or '\n'
+ local eol = t.is_os('win') and '\r\n' or '\n'
before_each(function()
-- Note: reset() is called explicitly in each test.
os.remove(fname)
diff --git a/test/functional/plugin/tohtml_spec.lua b/test/functional/plugin/tohtml_spec.lua
index 2ac0fe1fa3..200a5f34b2 100644
--- a/test/functional/plugin/tohtml_spec.lua
+++ b/test/functional/plugin/tohtml_spec.lua
@@ -1,13 +1,14 @@
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec = helpers.exec
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local fn = helpers.fn
-local api = helpers.api
-local insert = helpers.insert
+local clear = n.clear
+local exec = n.exec
+local exec_lua = n.exec_lua
+local eq = t.eq
+local fn = n.fn
+local api = n.api
+local insert = n.insert
local function html_syntax_match()
local styles =
diff --git a/test/functional/plugin/tutor_spec.lua b/test/functional/plugin/tutor_spec.lua
index 99538e1db0..9f381d45db 100644
--- a/test/functional/plugin/tutor_spec.lua
+++ b/test/functional/plugin/tutor_spec.lua
@@ -1,18 +1,20 @@
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local command = helpers.command
-local feed = helpers.feed
-local is_os = helpers.is_os
+
+local clear = n.clear
+local command = n.command
+local feed = n.feed
+local is_os = t.is_os
describe(':Tutor', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
clear({ args = { '--clean' } })
command('set cmdheight=0')
command('Tutor')
- screen = Screen.new(80, 30)
+ screen = Screen.new(81, 30)
screen:set_default_attr_ids({
[0] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
[1] = { bold = true },
@@ -20,6 +22,7 @@ describe(':Tutor', function()
[3] = { foreground = Screen.colors.SlateBlue },
[4] = { bold = true, foreground = Screen.colors.Brown },
[5] = { bold = true, foreground = Screen.colors.Magenta1 },
+ [6] = { italic = true },
})
screen:attach()
end)
@@ -27,71 +30,109 @@ describe(':Tutor', function()
it('applies {unix:…,win:…} transform', function()
local expected = is_os('win')
and [[
- {0: }^ |
- {0: } 3. To verify that a file was retrieved, cursor back and notice that there |
- {0: } are now two copies of Lesson 5.3, the original and the retrieved version. |
- {0: } |
- {0: }{1:NOTE}: You can also read the output of an external command. For example, |
- {0: } |
- {0: } :r {4:!}dir |
- {0: } |
- {0: } reads the output of the ls command and puts it below the cursor. |
- {0: } |
- {0: }{3:#}{5: Lesson 5 SUMMARY} |
- {0: } |
- {0: } 1. {2::!command} executes an external command. |
- {0: } |
- {0: } Some useful examples are: |
- {0: } :{4:!}dir - shows a directory listing |
- {0: } :{4:!}del FILENAME - removes file FILENAME |
- {0: } |
- {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with |
- {0: } name FILENAME. |
- {0: } |
- {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file |
- {0: } FILENAME. |
- {0: } |
- {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it |
- {0: } below the cursor position. |
- {0: } |
- {0: } 5. {2::r !dir} reads the output of the dir command and |
- {0: } puts it below the cursor position. |
- {0: } |
+ {0: }^ |
+ {0: } 3. To verify that a file was retrieved, cursor back and notice that there |
+ {0: } are now two copies of Lesson 5.3, the original and the retrieved version. |
+ {0: } |
+ {0: }{1:NOTE}: You can also read the output of an external command. For example, |
+ {0: } |
+ {0: } :r {4:!}dir |
+ {0: } |
+ {0: } reads the output of the ls command and puts it below the cursor. |
+ {0: } |
+ {0: }{3:#}{5: Lesson 5 SUMMARY} |
+ {0: } |
+ {0: } 1. {2::!command} executes an external command. |
+ {0: } |
+ {0: } Some useful examples are: |
+ {0: } :{4:!}dir - shows a directory listing |
+ {0: } :{4:!}del FILENAME - removes file FILENAME |
+ {0: } |
+ {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with |
+ {0: } name FILENAME. |
+ {0: } |
+ {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file |
+ {0: } FILENAME. |
+ {0: } |
+ {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it |
+ {0: } below the cursor position. |
+ {0: } |
+ {0: } 5. {2::r !dir} reads the output of the dir command and |
+ {0: } puts it below the cursor position. |
+ {0: } |
]]
or [[
- {0: }^ |
- {0: } 3. To verify that a file was retrieved, cursor back and notice that there |
- {0: } are now two copies of Lesson 5.3, the original and the retrieved version. |
- {0: } |
- {0: }{1:NOTE}: You can also read the output of an external command. For example, |
- {0: } |
- {0: } :r {4:!}ls |
- {0: } |
- {0: } reads the output of the ls command and puts it below the cursor. |
- {0: } |
- {0: }{3:#}{5: Lesson 5 SUMMARY} |
- {0: } |
- {0: } 1. {2::!command} executes an external command. |
- {0: } |
- {0: } Some useful examples are: |
- {0: } :{4:!}ls - shows a directory listing |
- {0: } :{4:!}rm FILENAME - removes file FILENAME |
- {0: } |
- {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with |
- {0: } name FILENAME. |
- {0: } |
- {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file |
- {0: } FILENAME. |
- {0: } |
- {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it |
- {0: } below the cursor position. |
- {0: } |
- {0: } 5. {2::r !ls} reads the output of the ls command and |
- {0: } puts it below the cursor position. |
- {0: } |
+ {0: }^ |
+ {0: } 3. To verify that a file was retrieved, cursor back and notice that there |
+ {0: } are now two copies of Lesson 5.3, the original and the retrieved version. |
+ {0: } |
+ {0: }{1:NOTE}: You can also read the output of an external command. For example, |
+ {0: } |
+ {0: } :r {4:!}ls |
+ {0: } |
+ {0: } reads the output of the ls command and puts it below the cursor. |
+ {0: } |
+ {0: }{3:#}{5: Lesson 5 SUMMARY} |
+ {0: } |
+ {0: } 1. {2::!command} executes an external command. |
+ {0: } |
+ {0: } Some useful examples are: |
+ {0: } :{4:!}ls - shows a directory listing |
+ {0: } :{4:!}rm FILENAME - removes file FILENAME |
+ {0: } |
+ {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with |
+ {0: } name FILENAME. |
+ {0: } |
+ {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file |
+ {0: } FILENAME. |
+ {0: } |
+ {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it |
+ {0: } below the cursor position. |
+ {0: } |
+ {0: } 5. {2::r !ls} reads the output of the ls command and |
+ {0: } puts it below the cursor position. |
+ {0: } |
]]
feed(':700<CR>zt')
screen:expect(expected)
end)
+
+ it('applies hyperlink highlighting', function()
+ local expected = [[
+ {0: }^ |
+ {0: }{3:#}{5: CONCLUSION} |
+ {0: } |
+ {0: }This was intended to give a brief overview of the Neovim editor, just enough to|
+ {0: }allow you to use it fairly easily. It is far from complete as Neovim has |
+ {0: }many many more commands. Consult the help often. |
+ {0: }There are also countless great tutorials and videos to be found online. |
+ {0: }Here's a bunch of them: |
+ {0: } |
+ {0: }- {6:Learn Vim Progressively}: |
+ {0: } {2:https://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/} |
+ {0: }- {6:Learning Vim in 2014}: |
+ {0: } {2:https://benmccormick.org/learning-vim-in-2014/} |
+ {0: }- {6:Vimcasts}: |
+ {0: } {2:http://vimcasts.org/} |
+ {0: }- {6:Vim Video-Tutorials by Derek Wyatt}: |
+ {0: } {2:http://derekwyatt.org/vim/tutorials/} |
+ {0: }- {6:Learn Vimscript the Hard Way}: |
+ {0: } {2:https://learnvimscriptthehardway.stevelosh.com/} |
+ {0: }- {6:7 Habits of Effective Text Editing}: |
+ {0: } {2:https://www.moolenaar.net/habits.html} |
+ {0: }- {6:vim-galore}: |
+ {0: } {2:https://github.com/mhinz/vim-galore} |
+ {0: } |
+ {0: }If you prefer a book, {6:Practical Vim} by Drew Neil is recommended often |
+ {0: }(the sequel, {6:Modern Vim}, includes material specific to Neovim). |
+ {0: } |
+ {0: }This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado |
+ {0: }School of Mines using ideas supplied by Charles Smith, Colorado State |
+ {0: }University. E-mail: {2:bware@mines.colorado.edu}. |
+ ]]
+
+ feed(':960<CR>zt')
+ screen:expect(expected)
+ end)
end)
diff --git a/test/functional/plugin/vim_syntax_spec.lua b/test/functional/plugin/vim_syntax_spec.lua
index 9396bbce5c..d99a69eab9 100644
--- a/test/functional/plugin/vim_syntax_spec.lua
+++ b/test/functional/plugin/vim_syntax_spec.lua
@@ -1,15 +1,16 @@
-local helpers = require('test.functional.helpers')(after_each)
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local clear = helpers.clear
-local exec = helpers.exec
-local api = helpers.api
+
+local clear = n.clear
+local exec = n.exec
+local api = n.api
describe('Vimscript syntax highlighting', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
clear()
- helpers.add_builddir_to_rtp()
+ n.add_builddir_to_rtp()
exec([[
setfiletype vim
syntax on