aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rw-r--r--test/functional/api/vim_spec.lua13
-rw-r--r--test/functional/core/channels_spec.lua5
-rw-r--r--test/functional/eval/api_functions_spec.lua9
-rw-r--r--test/functional/eval/execute_spec.lua8
-rw-r--r--test/functional/eval/json_functions_spec.lua9
-rw-r--r--test/functional/eval/msgpack_functions_spec.lua135
-rw-r--r--test/functional/eval/null_spec.lua2
-rw-r--r--test/functional/eval/writefile_spec.lua2
-rw-r--r--test/functional/ex_cmds/source_spec.lua61
-rw-r--r--test/functional/lua/api_spec.lua7
-rw-r--r--test/functional/lua/diagnostic_spec.lua831
-rw-r--r--test/functional/lua/luaeval_spec.lua34
-rw-r--r--test/functional/lua/vim_spec.lua2
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua114
-rw-r--r--test/functional/plugin/lsp_spec.lua25
-rw-r--r--test/functional/shada/errors_spec.lua5
-rw-r--r--test/functional/shada/variables_spec.lua8
17 files changed, 1113 insertions, 157 deletions
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 9aad8a1319..b4b2e63fb0 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -117,6 +117,19 @@ describe('API', function()
nvim('exec','autocmd BufAdd * :let x1 = "Hello"', false)
nvim('command', 'new foo')
eq('Hello', request('nvim_eval', 'g:x1'))
+
+ -- Line continuations
+ nvim('exec', [[
+ let abc = #{
+ \ a: 1,
+ "\ b: 2,
+ \ c: 3
+ \ }]], false)
+ eq({a = 1, c = 3}, request('nvim_eval', 'g:abc'))
+
+ -- try no spaces before continuations to catch off-by-one error
+ nvim('exec', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', false)
+ eq({a = 98}, request('nvim_eval', 'g:ab'))
end)
it('non-ASCII input', function()
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 1ef34c7318..6efa4f9b80 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -89,6 +89,9 @@ describe('channels', function()
command("call chansend(id, 'howdy')")
eq({"notification", "stdout", {id, {"[1, ['howdy'], 'stdin']"}}}, next_msg())
+ command("call chansend(id, 0z686f6c61)")
+ eq({"notification", "stdout", {id, {"[1, ['hola'], 'stdin']"}}}, next_msg())
+
command("call chanclose(id, 'stdin')")
expect_twostreams({{"notification", "stdout", {id, {"[1, [''], 'stdin']"}}},
{'notification', 'stdout', {id, {''}}}},
@@ -131,6 +134,8 @@ describe('channels', function()
command("call chansend(id, 'TEXT\n')")
expect_twoline(id, "stdout", "TEXT\r", "[1, ['TEXT', ''], 'stdin']")
+ command("call chansend(id, 0z426c6f6273210a)")
+ expect_twoline(id, "stdout", "Blobs!\r", "[1, ['Blobs!', ''], 'stdin']")
command("call chansend(id, 'neovan')")
eq({"notification", "stdout", {id, {"neovan"}}}, next_msg())
diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua
index 7d09a652ba..d07e74d40e 100644
--- a/test/functional/eval/api_functions_spec.lua
+++ b/test/functional/eval/api_functions_spec.lua
@@ -155,4 +155,13 @@ describe('eval-API', function()
pcall_err(command, "sandbox call nvim_input('ievil')"))
eq({''}, meths.buf_get_lines(0, 0, -1, true))
end)
+
+ it('converts blobs to API strings', function()
+ command('let g:v1 = nvim__id(0z68656c6c6f)')
+ command('let g:v2 = nvim__id(v:_null_blob)')
+ eq(1, eval('type(g:v1)'))
+ eq(1, eval('type(g:v2)'))
+ eq('hello', eval('g:v1'))
+ eq('', eval('g:v2'))
+ end)
end)
diff --git a/test/functional/eval/execute_spec.lua b/test/functional/eval/execute_spec.lua
index f52ac4e59b..fccf52935b 100644
--- a/test/functional/eval/execute_spec.lua
+++ b/test/functional/eval/execute_spec.lua
@@ -322,16 +322,16 @@ describe('execute()', function()
eq('Vim(call):E731: using Dictionary as a String', ret)
ret = exc_exec('call execute("echo add(1, 1)", "")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
ret = exc_exec('call execute(["echon 42", "echo add(1, 1)"], "")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
ret = exc_exec('call execute("echo add(1, 1)", "silent")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
ret = exc_exec('call execute(["echon 42", "echo add(1, 1)"], "silent")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
end)
end)
end)
diff --git a/test/functional/eval/json_functions_spec.lua b/test/functional/eval/json_functions_spec.lua
index 8dcaea806e..9b5e207c07 100644
--- a/test/functional/eval/json_functions_spec.lua
+++ b/test/functional/eval/json_functions_spec.lua
@@ -538,6 +538,11 @@ describe('json_encode() function', function()
eq('"þÿþ"', funcs.json_encode('þÿþ'))
end)
+ it('dumps blobs', function()
+ eq('[]', eval('json_encode(0z)'))
+ eq('[222, 173, 190, 239]', eval('json_encode(0zDEADBEEF)'))
+ end)
+
it('dumps numbers', function()
eq('0', funcs.json_encode(0))
eq('10', funcs.json_encode(10))
@@ -769,6 +774,10 @@ describe('json_encode() function', function()
eq('""', eval('json_encode($XXX_UNEXISTENT_VAR_XXX)'))
end)
+ it('can dump NULL blob', function()
+ eq('[]', eval('json_encode(v:_null_blob)'))
+ end)
+
it('can dump NULL list', function()
eq('[]', eval('json_encode(v:_null_list)'))
end)
diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua
index a8a413f68b..837b629858 100644
--- a/test/functional/eval/msgpack_functions_spec.lua
+++ b/test/functional/eval/msgpack_functions_spec.lua
@@ -13,6 +13,7 @@ describe('msgpack*() functions', function()
it(msg, function()
nvim('set_var', 'obj', obj)
eq(obj, eval('msgpackparse(msgpackdump(g:obj))'))
+ eq(obj, eval('msgpackparse(msgpackdump(g:obj, "B"))'))
end)
end
@@ -364,8 +365,7 @@ describe('msgpack*() functions', function()
command('let dumped = ["\\xC4\\x01\\n"]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq({{_TYPE={}, _VAL={'\n'}}}, eval('parsed'))
- eq(1, eval('parsed[0]._TYPE is v:msgpack_types.binary'))
+ eq({'\000'}, eval('parsed'))
eq(1, eval('dumped ==# dumped2'))
end)
@@ -392,56 +392,61 @@ describe('msgpack*() functions', function()
end)
end)
+local blobstr = function(list)
+ local l = {}
+ for i,v in ipairs(list) do
+ l[i] = v:gsub('\n', '\000')
+ end
+ return table.concat(l, '\n')
+end
+
+-- Test msgpackparse() with a readfile()-style list and a blob argument
+local parse_eq = function(expect, list_arg)
+ local blob_expr = '0z' .. blobstr(list_arg):gsub('(.)', function(c)
+ return ('%.2x'):format(c:byte())
+ end)
+ eq(expect, funcs.msgpackparse(list_arg))
+ command('let g:parsed = msgpackparse(' .. blob_expr .. ')')
+ eq(expect, eval('g:parsed'))
+end
+
describe('msgpackparse() function', function()
before_each(clear)
it('restores nil as v:null', function()
- command('let dumped = ["\\xC0"]')
- command('let parsed = msgpackparse(dumped)')
- eq('[v:null]', eval('string(parsed)'))
+ parse_eq(eval('[v:null]'), {'\192'})
end)
it('restores boolean false as v:false', function()
- command('let dumped = ["\\xC2"]')
- command('let parsed = msgpackparse(dumped)')
- eq({false}, eval('parsed'))
+ parse_eq({false}, {'\194'})
end)
it('restores boolean true as v:true', function()
- command('let dumped = ["\\xC3"]')
- command('let parsed = msgpackparse(dumped)')
- eq({true}, eval('parsed'))
+ parse_eq({true}, {'\195'})
end)
it('restores FIXSTR as special dict', function()
- command('let dumped = ["\\xa2ab"]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={'ab'}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={'ab'}}}, {'\162ab'})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.string'))
end)
it('restores BIN 8 as string', function()
- command('let dumped = ["\\xC4\\x02ab"]')
- eq({'ab'}, eval('msgpackparse(dumped)'))
+ parse_eq({'ab'}, {'\196\002ab'})
end)
it('restores FIXEXT1 as special dictionary', function()
- command('let dumped = ["\\xD4\\x10", ""]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={0x10, {"", ""}}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={0x10, {"", ""}}}}, {'\212\016', ''})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext'))
end)
it('restores MAP with BIN key as special dictionary', function()
- command('let dumped = ["\\x81\\xC4\\x01a\\xC4\\n"]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={{'a', ''}}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={{'a', ''}}}}, {'\129\196\001a\196\n'})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end)
it('restores MAP with duplicate STR keys as special dictionary', function()
command('let dumped = ["\\x82\\xA1a\\xC4\\n\\xA1a\\xC4\\n"]')
- -- FIXME Internal error bug
+ -- FIXME Internal error bug, can't use parse_eq() here
command('silent! let parsed = msgpackparse(dumped)')
eq({{_TYPE={}, _VAL={ {{_TYPE={}, _VAL={'a'}}, ''},
{{_TYPE={}, _VAL={'a'}}, ''}}} }, eval('parsed'))
@@ -451,9 +456,7 @@ describe('msgpackparse() function', function()
end)
it('restores MAP with MAP key as special dictionary', function()
- command('let dumped = ["\\x81\\x80\\xC4\\n"]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={{{}, ''}}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={{{}, ''}}}}, {'\129\128\196\n'})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end)
@@ -478,43 +481,65 @@ describe('msgpackparse() function', function()
end)
it('fails to parse a string', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse("abcdefghijklmnopqrstuvwxyz")'))
end)
it('fails to parse a number', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(127)'))
end)
it('fails to parse a dictionary', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse({})'))
end)
it('fails to parse a funcref', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(function("tr"))'))
end)
it('fails to parse a partial', function()
command('function T() dict\nendfunction')
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(function("T", [1, 2], {}))'))
end)
it('fails to parse a float', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(0.0)'))
end)
+
+ it('fails on incomplete msgpack string', function()
+ local expected = 'Vim(call):E475: Invalid argument: Incomplete msgpack string'
+ eq(expected, exc_exec([[call msgpackparse(["\xc4"])]]))
+ eq(expected, exc_exec([[call msgpackparse(["\xca", "\x02\x03"])]]))
+ eq(expected, exc_exec('call msgpackparse(0zc4)'))
+ eq(expected, exc_exec('call msgpackparse(0zca0a0203)'))
+ end)
+
+ it('fails when unable to parse msgpack string', function()
+ local expected = 'Vim(call):E475: Invalid argument: Failed to parse msgpack string'
+ eq(expected, exc_exec([[call msgpackparse(["\xc1"])]]))
+ eq(expected, exc_exec('call msgpackparse(0zc1)'))
+ end)
end)
describe('msgpackdump() function', function()
before_each(clear)
+ local dump_eq = function(exp_list, arg_expr)
+ eq(exp_list, eval('msgpackdump(' .. arg_expr .. ')'))
+ eq(blobstr(exp_list), eval('msgpackdump(' .. arg_expr .. ', "B")'))
+ end
+
it('dumps string as BIN 8', function()
- nvim('set_var', 'obj', {'Test'})
- eq({"\196\004Test"}, eval('msgpackdump(obj)'))
+ dump_eq({'\196\004Test'}, '["Test"]')
+ end)
+
+ it('dumps blob as BIN 8', function()
+ dump_eq({'\196\005Bl\nb!'}, '[0z426c006221]')
end)
it('can dump generic mapping with generic mapping keys and values', function()
@@ -522,56 +547,56 @@ describe('msgpackdump() function', function()
command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('call add(todump._VAL, [todumpv1, todumpv2])')
- eq({'\129\128\128'}, eval('msgpackdump([todump])'))
+ dump_eq({'\129\128\128'}, '[todump]')
end)
it('can dump v:true', function()
- eq({'\195'}, funcs.msgpackdump({true}))
+ dump_eq({'\195'}, '[v:true]')
end)
it('can dump v:false', function()
- eq({'\194'}, funcs.msgpackdump({false}))
+ dump_eq({'\194'}, '[v:false]')
end)
- it('can v:null', function()
- command('let todump = v:null')
+ it('can dump v:null', function()
+ dump_eq({'\192'}, '[v:null]')
end)
it('can dump special bool mapping (true)', function()
command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}')
- eq({'\195'}, eval('msgpackdump([todump])'))
+ dump_eq({'\195'}, '[todump]')
end)
it('can dump special bool mapping (false)', function()
command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}')
- eq({'\194'}, eval('msgpackdump([todump])'))
+ dump_eq({'\194'}, '[todump]')
end)
it('can dump special nil mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}')
- eq({'\192'}, eval('msgpackdump([todump])'))
+ dump_eq({'\192'}, '[todump]')
end)
it('can dump special ext mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
- eq({'\212\005', ''}, eval('msgpackdump([todump])'))
+ dump_eq({'\212\005', ''}, '[todump]')
end)
it('can dump special array mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
- eq({'\146\005\145\196\n'}, eval('msgpackdump([todump])'))
+ dump_eq({'\146\005\145\196\n'}, '[todump]')
end)
it('can dump special UINT64_MAX mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.integer}')
command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
- eq({'\207\255\255\255\255\255\255\255\255'}, eval('msgpackdump([todump])'))
+ dump_eq({'\207\255\255\255\255\255\255\255\255'}, '[todump]')
end)
it('can dump special INT64_MIN mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.integer}')
command('let todump._VAL = [-1, 2, 0, 0]')
- eq({'\211\128\n\n\n\n\n\n\n'}, eval('msgpackdump([todump])'))
+ dump_eq({'\211\128\n\n\n\n\n\n\n'}, '[todump]')
end)
it('fails to dump a function reference', function()
@@ -610,13 +635,13 @@ describe('msgpackdump() function', function()
it('can dump dict with two same dicts inside', function()
command('let inter = {}')
command('let todump = {"a": inter, "b": inter}')
- eq({"\130\161a\128\161b\128"}, eval('msgpackdump([todump])'))
+ dump_eq({"\130\161a\128\161b\128"}, '[todump]')
end)
it('can dump list with two same lists inside', function()
command('let inter = []')
command('let todump = [inter, inter]')
- eq({"\146\144\144"}, eval('msgpackdump([todump])'))
+ dump_eq({"\146\144\144"}, '[todump]')
end)
it('fails to dump a recursive list in a special dict', function()
@@ -667,9 +692,9 @@ describe('msgpackdump() function', function()
exc_exec('call msgpackdump()'))
end)
- it('fails when called with two arguments', function()
+ it('fails when called with three arguments', function()
eq('Vim(call):E118: Too many arguments for function: msgpackdump',
- exc_exec('call msgpackdump(["", ""], 1)'))
+ exc_exec('call msgpackdump(["", ""], 1, 2)'))
end)
it('fails to dump a string', function()
@@ -711,9 +736,13 @@ describe('msgpackdump() function', function()
end)
it('can dump NULL string', function()
- eq({'\196\n'}, eval('msgpackdump([$XXX_UNEXISTENT_VAR_XXX])'))
- eq({'\196\n'}, eval('msgpackdump([{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}])'))
- eq({'\160'}, eval('msgpackdump([{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}])'))
+ dump_eq({'\196\n'}, '[$XXX_UNEXISTENT_VAR_XXX]')
+ dump_eq({'\196\n'}, '[{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
+ dump_eq({'\160'}, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
+ end)
+
+ it('can dump NULL blob', function()
+ eq({'\196\n'}, eval('msgpackdump([v:_null_blob])'))
end)
it('can dump NULL list', function()
diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua
index f866aca3ed..bc88e6c8b3 100644
--- a/test/functional/eval/null_spec.lua
+++ b/test/functional/eval/null_spec.lua
@@ -44,7 +44,7 @@ describe('NULL', function()
-- Incorrect behaviour
-- FIXME Should error out with different message
null_test('makes :unlet act as if it is not a list', ':unlet L[0]',
- 'Vim(unlet):E689: Can only index a List or Dictionary')
+ 'Vim(unlet):E689: Can only index a List, Dictionary or Blob')
-- Subjectable behaviour
diff --git a/test/functional/eval/writefile_spec.lua b/test/functional/eval/writefile_spec.lua
index 356680ba7c..14be8c377c 100644
--- a/test/functional/eval/writefile_spec.lua
+++ b/test/functional/eval/writefile_spec.lua
@@ -119,7 +119,7 @@ describe('writefile()', function()
eq('\nE118: Too many arguments for function: writefile',
redir_exec(('call writefile([], "%s", "b", 1)'):format(fname)))
for _, arg in ipairs({'0', '0.0', 'function("tr")', '{}', '"test"'}) do
- eq('\nE686: Argument of writefile() must be a List',
+ eq('\nE475: Invalid argument: writefile() first argument must be a List or a Blob',
redir_exec(('call writefile(%s, "%s", "b")'):format(arg, fname)))
end
for _, args in ipairs({'[], %s, "b"', '[], "' .. fname .. '", %s'}) do
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
index 37c97f519a..bdf6ae76d1 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -8,6 +8,8 @@ local feed = helpers.feed
local feed_command = helpers.feed_command
local write_file = helpers.write_file
local exec = helpers.exec
+local exc_exec = helpers.exc_exec
+local exec_lua = helpers.exec_lua
local eval = helpers.eval
local exec_capture = helpers.exec_capture
local neq = helpers.neq
@@ -18,16 +20,30 @@ describe(':source', function()
end)
it('current buffer', function()
- insert('let a = 2')
+ insert([[
+ let a = 2
+ let b = #{
+ \ k: "v"
+ "\ (o_o)
+ \ }]])
+
command('source')
eq('2', meths.exec('echo a', true))
+ eq("{'k': 'v'}", meths.exec('echo b', true))
+
+ exec('set cpoptions+=C')
+ eq('Vim(let):E15: Invalid expression: #{', exc_exec('source'))
end)
it('selection in current buffer', function()
- insert(
- 'let a = 2\n'..
- 'let a = 3\n'..
- 'let a = 4\n')
+ insert([[
+ let a = 2
+ let a = 3
+ let a = 4
+ let b = #{
+ "\ (>_<)
+ \ K: "V"
+ \ }]])
-- Source the 2nd line only
feed('ggjV')
@@ -38,13 +54,26 @@ describe(':source', function()
feed('ggjVG')
feed_command(':source')
eq('4', meths.exec('echo a', true))
+ eq("{'K': 'V'}", meths.exec('echo b', true))
+
+ exec('set cpoptions+=C')
+ eq('Vim(let):E15: Invalid expression: #{', exc_exec("'<,'>source"))
+ end)
+
+ it('does not break if current buffer is modified while sourced', function()
+ insert [[
+ bwipeout!
+ let a = 123
+ ]]
+ command('source')
+ eq('123', meths.exec('echo a', true))
end)
it('multiline heredoc command', function()
- insert(
- 'lua << EOF\n'..
- 'y = 4\n'..
- 'EOF\n')
+ insert([[
+ lua << EOF
+ y = 4
+ EOF]])
command('source')
eq('4', meths.exec('echo luaeval("y")', true))
@@ -67,13 +96,21 @@ describe(':source', function()
vim.g.b = 5
vim.g.b = 6
vim.g.b = 7
+ a = [=[
+ "\ a
+ \ b]=]
]])
command('edit '..test_file)
+
feed('ggjV')
feed_command(':source')
-
eq(6, eval('g:b'))
+
+ feed('GVkk')
+ feed_command(':source')
+ eq(' "\\ a\n \\ b', exec_lua('return _G.a'))
+
os.remove(test_file)
end)
@@ -84,12 +121,16 @@ describe(':source', function()
vim.g.c = 10
vim.g.c = 11
vim.g.c = 12
+ a = [=[
+ \ 1
+ "\ 2]=]
]])
command('edit '..test_file)
feed_command(':source')
eq(12, eval('g:c'))
+ eq(' \\ 1\n "\\ 2', exec_lua('return _G.a'))
os.remove(test_file)
end)
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua
index 896554f7a3..fdf79d55b2 100644
--- a/test/functional/lua/api_spec.lua
+++ b/test/functional/lua/api_spec.lua
@@ -15,7 +15,7 @@ describe('luaeval(vim.api.…)', function()
describe('nvim_buf_get_lines', function()
it('works', function()
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
- eq({{_TYPE={}, _VAL={'a\nb'}}},
+ eq({'a\000b'},
funcs.luaeval('vim.api.nvim_buf_get_lines(1, 2, 3, false)'))
end)
end)
@@ -23,7 +23,7 @@ describe('luaeval(vim.api.…)', function()
it('works', function()
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
eq(NIL, funcs.luaeval('vim.api.nvim_buf_set_lines(1, 1, 2, false, {"b\\0a"})'))
- eq({'abc', {_TYPE={}, _VAL={'b\na'}}, {_TYPE={}, _VAL={'a\nb'}}, 'ttt'},
+ eq({'abc', 'b\000a', 'a\000b', 'ttt'},
funcs.luaeval('vim.api.nvim_buf_get_lines(1, 0, 4, false)'))
end)
end)
@@ -64,15 +64,18 @@ describe('luaeval(vim.api.…)', function()
it('correctly converts from API objects', function()
eq(1, funcs.luaeval('vim.api.nvim_eval("1")'))
eq('1', funcs.luaeval([[vim.api.nvim_eval('"1"')]]))
+ eq('Blobby', funcs.luaeval('vim.api.nvim_eval("0z426c6f626279")'))
eq({}, funcs.luaeval('vim.api.nvim_eval("[]")'))
eq({}, funcs.luaeval('vim.api.nvim_eval("{}")'))
eq(1, funcs.luaeval('vim.api.nvim_eval("1.0")'))
+ eq('\000', funcs.luaeval('vim.api.nvim_eval("0z00")'))
eq(true, funcs.luaeval('vim.api.nvim_eval("v:true")'))
eq(false, funcs.luaeval('vim.api.nvim_eval("v:false")'))
eq(NIL, funcs.luaeval('vim.api.nvim_eval("v:null")'))
eq(0, eval([[type(luaeval('vim.api.nvim_eval("1")'))]]))
eq(1, eval([[type(luaeval('vim.api.nvim_eval("''1''")'))]]))
+ eq(1, eval([[type(luaeval('vim.api.nvim_eval("0zbeef")'))]]))
eq(3, eval([[type(luaeval('vim.api.nvim_eval("[]")'))]]))
eq(4, eval([[type(luaeval('vim.api.nvim_eval("{}")'))]]))
eq(5, eval([[type(luaeval('vim.api.nvim_eval("1.0")'))]]))
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
new file mode 100644
index 0000000000..8da33173a2
--- /dev/null
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -0,0 +1,831 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local command = helpers.command
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local nvim = helpers.nvim
+
+describe('vim.diagnostic', function()
+ before_each(function()
+ clear()
+
+ exec_lua [[
+ require('vim.diagnostic')
+
+ function make_error(msg, x1, y1, x2, y2)
+ return {
+ lnum = x1,
+ col = y1,
+ end_lnum = x2,
+ end_col = y2,
+ message = msg,
+ severity = vim.diagnostic.severity.ERROR,
+ }
+ end
+
+ function make_warning(msg, x1, y1, x2, y2)
+ return {
+ lnum = x1,
+ col = y1,
+ end_lnum = x2,
+ end_col = y2,
+ message = msg,
+ severity = vim.diagnostic.severity.WARN,
+ }
+ end
+
+ function make_information(msg, x1, y1, x2, y2)
+ return {
+ lnum = x1,
+ col = y1,
+ end_lnum = x2,
+ end_col = y2,
+ message = msg,
+ severity = vim.diagnostic.severity.INFO,
+ }
+ end
+
+ function make_hint(msg, x1, y1, x2, y2)
+ return {
+ lnum = x1,
+ col = y1,
+ end_lnum = x2,
+ end_col = y2,
+ message = msg,
+ severity = vim.diagnostic.severity.HINT,
+ }
+ end
+
+ function count_diagnostics(bufnr, severity, namespace)
+ return #vim.diagnostic.get(bufnr, {severity = severity, namespace = namespace})
+ end
+
+ function count_extmarks(bufnr, namespace)
+ return #vim.api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, {})
+ end
+ ]]
+
+ exec_lua([[
+ diagnostic_ns = vim.api.nvim_create_namespace("diagnostic_spec")
+ other_ns = vim.api.nvim_create_namespace("other_namespace")
+ diagnostic_bufnr = vim.api.nvim_create_buf(true, false)
+ local lines = {"1st line of text", "2nd line of text", "wow", "cool", "more", "lines"}
+ vim.fn.bufload(diagnostic_bufnr)
+ vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, 1, false, lines)
+ return diagnostic_bufnr
+ ]])
+ end)
+
+ after_each(function()
+ clear()
+ end)
+
+ it('creates highlight groups', function()
+ command('runtime plugin/diagnostic.vim')
+ eq({
+ 'DiagnosticError',
+ 'DiagnosticFloatingError',
+ 'DiagnosticFloatingHint',
+ 'DiagnosticFloatingInfo',
+ 'DiagnosticFloatingWarn',
+ 'DiagnosticHint',
+ 'DiagnosticInfo',
+ 'DiagnosticSignError',
+ 'DiagnosticSignHint',
+ 'DiagnosticSignInfo',
+ 'DiagnosticSignWarn',
+ 'DiagnosticUnderlineError',
+ 'DiagnosticUnderlineHint',
+ 'DiagnosticUnderlineInfo',
+ 'DiagnosticUnderlineWarn',
+ 'DiagnosticVirtualTextError',
+ 'DiagnosticVirtualTextHint',
+ 'DiagnosticVirtualTextInfo',
+ 'DiagnosticVirtualTextWarn',
+ 'DiagnosticWarn',
+ }, exec_lua([[return vim.fn.getcompletion('Diagnostic', 'highlight')]]))
+ end)
+
+ it('retrieves diagnostics from all buffers and namespaces', function()
+ local result = exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, 1, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 2, 1, 2, 1),
+ })
+ vim.diagnostic.set(other_ns, 2, {
+ make_error('Diagnostic #3', 3, 1, 3, 1),
+ })
+ return vim.diagnostic.get()
+ ]]
+ eq(3, #result)
+ eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == 1 end, ...)]], result))
+ eq('Diagnostic #1', result[1].message)
+ end)
+
+ it('saves and count a single error', function()
+ eq(1, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)
+ ]])
+ end)
+
+ it('saves and count multiple errors', function()
+ eq(2, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 2, 1, 2, 1),
+ })
+ return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)
+ ]])
+ end)
+
+ it('saves and count from multiple namespaces', function()
+ eq({1, 1, 2}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1', 1, 1, 1, 1),
+ })
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 2', 1, 1, 1, 1),
+ })
+ return {
+ -- First namespace
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ -- Second namespace
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, other_ns),
+ -- All namespaces
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR),
+ }
+ ]])
+ end)
+
+ it('saves and count from multiple namespaces with respect to severity', function()
+ eq({3, 0, 3}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ make_error('Diagnostic From Server 1:2', 2, 2, 2, 2),
+ make_error('Diagnostic From Server 1:3', 2, 3, 3, 2),
+ })
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, {
+ make_warning('Warning From Server 2', 3, 3, 3, 3),
+ })
+ return {
+ -- Namespace 1
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ -- Namespace 2
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, other_ns),
+ -- All namespaces
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR),
+ }
+ ]])
+ end)
+
+ it('handles one namespace clearing highlights while the other still has highlights', function()
+ -- 1 Error (1)
+ -- 1 Warning (2)
+ -- 1 Warning (2) + 1 Warning (1)
+ -- 2 highlights and 2 underlines (since error)
+ -- 1 highlight + 1 underline
+ local all_highlights = {1, 1, 2, 4, 2}
+ eq(all_highlights, exec_lua [[
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ -- Clear diagnostics from namespace 1, and make sure we have the right amount of stuff for namespace 2
+ eq({1, 1, 2, 0, 2}, exec_lua [[
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ -- Show diagnostics from namespace 1 again
+ eq(all_highlights, exec_lua([[
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]]))
+ end)
+
+ it('does not display diagnostics when disabled', function()
+ eq({0, 2}, exec_lua [[
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+
+ return {
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ eq({4, 0}, exec_lua [[
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.disable(diagnostic_bufnr, other_ns)
+
+ return {
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+ end)
+
+ describe('reset()', function()
+ it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
+ -- 1 Error (1)
+ -- 1 Warning (2)
+ -- 1 Warning (2) + 1 Warning (1)
+ -- 2 highlights and 2 underlines (since error)
+ -- 1 highlight + 1 underline
+ local all_highlights = {1, 1, 2, 4, 2}
+ eq(all_highlights, exec_lua [[
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ -- Reset diagnostics from namespace 1
+ exec_lua([[ vim.diagnostic.reset(diagnostic_ns) ]])
+
+ -- Make sure we have the right diagnostic count
+ eq({0, 1, 1, 0, 2} , exec_lua [[
+ local diagnostic_count = {}
+ vim.wait(100, function () diagnostic_count = {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ } end )
+ return diagnostic_count
+ ]])
+
+ -- Reset diagnostics from namespace 2
+ exec_lua([[ vim.diagnostic.reset(other_ns) ]])
+
+ -- Make sure we have the right diagnostic count
+ eq({0, 0, 0, 0, 0}, exec_lua [[
+ local diagnostic_count = {}
+ vim.wait(100, function () diagnostic_count = {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ } end )
+ return diagnostic_count
+ ]])
+
+ end)
+ end)
+
+ describe('get_next_pos()', function()
+ it('can find the next pos with only one namespace', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ return vim.diagnostic.get_next_pos()
+ ]])
+ end)
+
+ it('can find next pos with two errors', function()
+ eq({4, 4}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('can cycle when position is past error', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('will not cycle when wrap is off', function()
+ eq(false, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns, wrap = false }
+ ]])
+ end)
+
+ it('can cycle even from the last line', function()
+ eq({4, 4}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+ end)
+
+ describe('get_prev_pos()', function()
+ it('can find the prev pos with only one namespace', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos()
+ ]])
+ end)
+
+ it('can find prev pos with two errors', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('can cycle when position is past error', function()
+ eq({4, 4}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('respects wrap parameter', function()
+ eq(false, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns, wrap = false}
+ ]])
+ end)
+ end)
+
+ describe('get()', function()
+ it('returns an empty table when no diagnostics are present', function()
+ eq({}, exec_lua [[return vim.diagnostic.get(diagnostic_bufnr, {namespace=diagnostic_ns})]])
+ end)
+
+ it('returns all diagnostics when no severity is supplied', function()
+ eq(2, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 5),
+ })
+
+ return #vim.diagnostic.get(diagnostic_bufnr)
+ ]])
+ end)
+
+ it('returns only requested diagnostics when severity is supplied', function()
+ eq({2, 3, 2}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 5),
+ make_information("Ignored information", 1, 1, 2, 5),
+ make_hint("Here's a hint", 1, 1, 2, 5),
+ })
+
+ return {
+ #vim.diagnostic.get(diagnostic_bufnr, { severity = {min=vim.diagnostic.severity.WARN} }),
+ #vim.diagnostic.get(diagnostic_bufnr, { severity = {max=vim.diagnostic.severity.WARN} }),
+ #vim.diagnostic.get(diagnostic_bufnr, {
+ severity = {
+ min=vim.diagnostic.severity.INFO,
+ max=vim.diagnostic.severity.WARN,
+ }
+ }),
+ }
+ ]])
+ end)
+
+ it('allows filtering by line', function()
+ eq(1, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 5),
+ make_information("Ignored information", 1, 1, 2, 5),
+ make_error("Error On Other Line", 2, 1, 1, 5),
+ })
+
+ return #vim.diagnostic.get(diagnostic_bufnr, {lnum = 2})
+ ]])
+ end)
+ end)
+
+ describe('config()', function()
+ it('can use functions for config values', function()
+ exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = function() return true end,
+ }, diagnostic_ns)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+
+ -- Now, don't enable virtual text.
+ -- We should have one less extmark displayed.
+ exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = function() return false end,
+ }, diagnostic_ns)
+ ]]
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ end)
+
+ it('allows filtering by severity', function()
+ local get_extmark_count_with_severity = function(min_severity)
+ return exec_lua([[
+ vim.diagnostic.config({
+ underline = false,
+ virtual_text = {
+ severity = {min=...},
+ },
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]], min_severity)
+ end
+
+ -- No messages with Error or higher
+ eq(0, get_extmark_count_with_severity("ERROR"))
+
+ -- But now we don't filter it
+ eq(1, get_extmark_count_with_severity("WARN"))
+ eq(1, get_extmark_count_with_severity("HINT"))
+ end)
+ end)
+
+ describe('set()', function()
+ it('can perform updates after insert_leave', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = false,
+ })
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- No diagnostics displayed yet.
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ end)
+
+ it('does not perform updates when not needed', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = false,
+ virtual_text = true,
+ })
+
+ -- Count how many times we call display.
+ SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
+
+ DisplayCount = 0
+ vim.diagnostic._set_virtual_text = function(...)
+ DisplayCount = DisplayCount + 1
+ return SetVirtualTextOriginal(...)
+ end
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- No diagnostics displayed yet.
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(0, exec_lua [[return DisplayCount]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(1, exec_lua [[return DisplayCount]])
+
+ -- Go in and out of insert mode one more time.
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ -- Should not have set the virtual text again.
+ eq(1, exec_lua [[return DisplayCount]])
+ end)
+
+ it('never sets virtual text, in combination with insert leave', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = false,
+ virtual_text = false,
+ })
+
+ -- Count how many times we call display.
+ SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
+
+ DisplayCount = 0
+ vim.diagnostic._set_virtual_text = function(...)
+ DisplayCount = DisplayCount + 1
+ return SetVirtualTextOriginal(...)
+ end
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- No diagnostics displayed yet.
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(0, exec_lua [[return DisplayCount]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(0, exec_lua [[return DisplayCount]])
+
+ -- Go in and out of insert mode one more time.
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ -- Should not have set the virtual text still.
+ eq(0, exec_lua [[return DisplayCount]])
+ end)
+
+ it('can perform updates while in insert mode, if desired', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = true,
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- Diagnostics are displayed, because the user wanted them that way!
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ end)
+
+ it('can set diagnostics without displaying them', function()
+ eq(0, exec_lua [[
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ })
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(2, exec_lua [[
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+ end)
+
+ it('can set display options', function()
+ eq(0, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ }, { virtual_text = false, underline = false })
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(1, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ }, { virtual_text = true, underline = false })
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+ end)
+ end)
+
+ describe('show_line_diagnostics()', function()
+ it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function()
+ -- Two lines:
+ -- Diagnostic:
+ -- 1. <msg>
+ eq(2, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics()
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+
+ it('creates floating window and returns popup bufnr and winnr without header, if requested', function()
+ -- One line (since no header):
+ -- 1. <msg>
+ eq(1, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {show_header = false}
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+ end)
+
+ describe('set_signs()', function()
+ -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...??
+ pending('sets signs by default', function()
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = true,
+ signs = true,
+ })
+
+ local diagnostics = {
+ make_error('Delayed Diagnostic', 1, 1, 1, 2),
+ make_error('Delayed Diagnostic', 3, 3, 3, 3),
+ }
+
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+
+ vim.diagnostic._set_signs(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ -- return vim.fn.sign_getplaced()
+ ]]
+
+ nvim("input", "o")
+ nvim("input", "<esc>")
+
+ -- TODO(tjdevries): Find a way to get the signs to display in the test...
+ eq(nil, exec_lua [[
+ return im.fn.sign_getplaced()[1].signs
+ ]])
+ end)
+ end)
+
+ describe('setloclist()', function()
+ it('sets diagnostics in lnum order', function()
+ local loc_list = exec_lua [[
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Farther Diagnostic', 4, 4, 4, 4),
+ make_error('Lower Diagnostic', 1, 1, 1, 1),
+ })
+
+ vim.diagnostic.setloclist()
+
+ return vim.fn.getloclist(0)
+ ]]
+
+ assert(loc_list[1].lnum < loc_list[2].lnum)
+ end)
+
+ it('sets diagnostics in lnum order, regardless of namespace', function()
+ local loc_list = exec_lua [[
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Lower Diagnostic', 1, 1, 1, 1),
+ })
+
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, {
+ make_warning('Farther Diagnostic', 4, 4, 4, 4),
+ })
+
+ vim.diagnostic.setloclist()
+
+ return vim.fn.getloclist(0)
+ ]]
+
+ assert(loc_list[1].lnum < loc_list[2].lnum)
+ end)
+ end)
+end)
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 8ef77faa0f..255e99032f 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -63,11 +63,10 @@ describe('luaeval()', function()
eq('\n[[...@0]]', funcs.execute('echo luaeval("l")'))
end)
end)
- describe('strings', function()
- it('are successfully converted to special dictionaries', function()
+ describe('strings with NULs', function()
+ it('are successfully converted to blobs', function()
command([[let s = luaeval('"\0"')]])
- eq({_TYPE={}, _VAL={'\n'}}, meths.get_var('s'))
- eq(1, funcs.eval('s._TYPE is v:msgpack_types.binary'))
+ eq('\000', meths.get_var('s'))
end)
it('are successfully converted to special dictionaries in table keys',
function()
@@ -76,13 +75,10 @@ describe('luaeval()', function()
eq(1, funcs.eval('d._TYPE is v:msgpack_types.map'))
eq(1, funcs.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string'))
end)
- it('are successfully converted to special dictionaries from a list',
+ it('are successfully converted to blobs from a list',
function()
command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]])
- eq({'abc', {_TYPE={}, _VAL={'a\nb'}}, {_TYPE={}, _VAL={'c\nd'}}, 'def'},
- meths.get_var('l'))
- eq(1, funcs.eval('l[1]._TYPE is v:msgpack_types.binary'))
- eq(1, funcs.eval('l[2]._TYPE is v:msgpack_types.binary'))
+ eq({'abc', 'a\000b', 'c\000d', 'def'}, meths.get_var('l'))
end)
end)
@@ -100,9 +96,9 @@ describe('luaeval()', function()
eq(1, eval('type(luaeval("\'test\'"))'))
eq('', funcs.luaeval('""'))
- eq({_TYPE={}, _VAL={'\n'}}, funcs.luaeval([['\0']]))
- eq({_TYPE={}, _VAL={'\n', '\n'}}, funcs.luaeval([['\0\n\0']]))
- eq(1, eval([[luaeval('"\0\n\0"')._TYPE is v:msgpack_types.binary]]))
+ eq('\000', funcs.luaeval([['\0']]))
+ eq('\000\n\000', funcs.luaeval([['\0\n\0']]))
+ eq(10, eval([[type(luaeval("'\\0\\n\\0'"))]]))
eq(true, funcs.luaeval('true'))
eq(false, funcs.luaeval('false'))
@@ -122,12 +118,11 @@ describe('luaeval()', function()
local level = 30
eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s))
- eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}},
+ eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}},
funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]]))
- eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][1]._TYPE is v:msgpack_types.binary]]))
- eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}}},
+ eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}}}},
funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]]))
end)
@@ -175,8 +170,8 @@ describe('luaeval()', function()
end
it('correctly passes special dictionaries', function()
- eq({'binary', {'\n', '\n'}}, luaevalarg(sp('binary', '["\\n", "\\n"]')))
- eq({'binary', {'\n', '\n'}}, luaevalarg(sp('string', '["\\n", "\\n"]')))
+ eq({0, '\000\n\000'}, luaevalarg(sp('binary', '["\\n", "\\n"]')))
+ eq({0, '\000\n\000'}, luaevalarg(sp('string', '["\\n", "\\n"]')))
eq({0, true}, luaevalarg(sp('boolean', 1)))
eq({0, false}, luaevalarg(sp('boolean', 0)))
eq({0, NIL}, luaevalarg(sp('nil', 0)))
@@ -458,6 +453,9 @@ describe('v:lua', function()
function mymod.crashy()
nonexistent()
end
+ function mymod.whatis(value)
+ return type(value) .. ": " .. tostring(value)
+ end
function mymod.omni(findstart, base)
if findstart == 1 then
return 5
@@ -476,6 +474,8 @@ describe('v:lua', function()
eq(true, exec_lua([[return _G.val == vim.NIL]]))
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
eq("hey eval", meths.get_current_line())
+ eq("string: abc", eval('v:lua.mymod.whatis(0z616263)'))
+ eq("string: ", eval('v:lua.mymod.whatis(v:_null_blob)'))
eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
pcall_err(eval, 'v:lua.mymod.crashy()'))
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 2bedbd1453..a066cfbc10 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -739,7 +739,7 @@ describe('lua stdlib', function()
eq({NIL, NIL}, exec_lua([[return vim.fn.Nilly()]]))
-- error handling
- eq({false, 'Vim:E714: List required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
+ eq({false, 'Vim:E897: List or Blob required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
end)
it('vim.fn should error when calling API function', function()
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index e4fe1c1992..2a6d7de634 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local command = helpers.command
local clear = helpers.clear
local exec_lua = helpers.exec_lua
local eq = helpers.eq
@@ -9,7 +10,10 @@ describe('vim.lsp.diagnostic', function()
local fake_uri
before_each(function()
- clear()
+ clear {env={
+ NVIM_LUA_NOTRACK="1";
+ VIMRUNTIME=os.getenv"VIMRUNTIME";
+ }}
exec_lua [[
require('vim.lsp')
@@ -44,7 +48,7 @@ describe('vim.lsp.diagnostic', function()
count_of_extmarks_for_client = function(bufnr, client_id)
return #vim.api.nvim_buf_get_extmarks(
- bufnr, vim.lsp.diagnostic._get_diagnostic_namespace(client_id), 0, -1, {}
+ bufnr, vim.lsp.diagnostic.get_namespace(client_id), 0, -1, {}
)
end
]]
@@ -86,39 +90,6 @@ describe('vim.lsp.diagnostic', function()
eq(2, #result[1])
eq('Diagnostic #1', result[1][1].message)
end)
- it('Can convert diagnostic to quickfix items format', function()
- local bufnr = exec_lua([[
- local fake_uri = ...
- return vim.uri_to_bufnr(fake_uri)
- ]], fake_uri)
- local result = exec_lua([[
- local bufnr = ...
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 2, 1, 2, 1),
- }, bufnr, 1
- )
- return vim.lsp.util.diagnostics_to_items(vim.lsp.diagnostic.get_all())
- ]], bufnr)
- local expected = {
- {
- bufnr = bufnr,
- col = 2,
- lnum = 2,
- text = 'Diagnostic #1',
- type = 'E'
- },
- {
- bufnr = bufnr,
- col = 2,
- lnum = 3,
- text = 'Diagnostic #2',
- type = 'E'
- },
- }
- eq(expected, result)
- end)
it('should be able to save and count a single client error', function()
eq(1, exec_lua [[
vim.lsp.diagnostic.save(
@@ -218,7 +189,7 @@ describe('vim.lsp.diagnostic', function()
-- Clear diagnostics from server 1, and make sure we have the right amount of stuff for client 2
eq({1, 1, 2, 0, 2}, exec_lua [[
- vim.lsp.diagnostic.clear(diagnostic_bufnr, 1)
+ vim.lsp.diagnostic.disable(diagnostic_bufnr, 1)
return {
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
@@ -230,7 +201,7 @@ describe('vim.lsp.diagnostic', function()
-- Show diagnostics from server 1 again
eq(all_highlights, exec_lua([[
- vim.lsp.diagnostic.display(nil, diagnostic_bufnr, 1)
+ vim.lsp.diagnostic.enable(diagnostic_bufnr, 1)
return {
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
@@ -575,10 +546,10 @@ describe('vim.lsp.diagnostic', function()
})
-- Count how many times we call display.
- SetVirtualTextOriginal = vim.lsp.diagnostic.set_virtual_text
+ SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
DisplayCount = 0
- vim.lsp.diagnostic.set_virtual_text = function(...)
+ vim.diagnostic._set_virtual_text = function(...)
DisplayCount = DisplayCount + 1
return SetVirtualTextOriginal(...)
end
@@ -719,7 +690,7 @@ describe('vim.lsp.diagnostic', function()
return vim.api.nvim_buf_get_extmarks(
diagnostic_bufnr,
- vim.lsp.diagnostic._get_diagnostic_namespace(1),
+ vim.lsp.diagnostic.get_namespace(1),
0,
-1,
{ details = true }
@@ -756,7 +727,7 @@ describe('vim.lsp.diagnostic', function()
return vim.api.nvim_buf_get_extmarks(
diagnostic_bufnr,
- vim.lsp.diagnostic._get_diagnostic_namespace(1),
+ vim.lsp.diagnostic.get_namespace(1),
0,
-1,
{ details = true }
@@ -798,6 +769,40 @@ describe('vim.lsp.diagnostic', function()
eq(1, get_extmark_count_with_severity("Warning"))
eq(1, get_extmark_count_with_severity("Hint"))
end)
+
+ it('correctly handles UTF-16 offsets', function()
+ local line = "All 💼 and no 🎉 makes Jack a dull 👦"
+ local result = exec_lua([[
+ local line = ...
+ local client_id = vim.lsp.start_client {
+ cmd_env = {
+ NVIM_LUA_NOTRACK = "1";
+ };
+ cmd = {
+ vim.v.progpath, '-es', '-u', 'NONE', '--headless'
+ };
+ offset_encoding = "utf-16";
+ }
+
+ vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line})
+
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
+ uri = fake_uri,
+ diagnostics = {
+ make_error('UTF-16 Diagnostic', 0, 7, 0, 8),
+ }
+ }, {client_id=client_id}
+ )
+
+ local diags = vim.diagnostic.get(diagnostic_bufnr)
+ vim.lsp.stop_client(client_id)
+ vim.lsp._vim_exit_handler()
+ return diags
+ ]], line)
+ eq(1, #result)
+ eq(exec_lua([[return vim.str_byteindex(..., 7, true)]], line), result[1].col)
+ eq(exec_lua([[return vim.str_byteindex(..., 8, true)]], line), result[1].end_col)
+ end)
end)
describe('lsp.util.show_line_diagnostics', function()
@@ -940,4 +945,31 @@ describe('vim.lsp.diagnostic', function()
assert(loc_list[1].lnum < loc_list[2].lnum)
end)
end)
+
+ it('highlight groups', function()
+ command('runtime plugin/diagnostic.vim')
+ eq({
+ 'LspDiagnosticsDefaultError',
+ 'LspDiagnosticsDefaultHint',
+ 'LspDiagnosticsDefaultInformation',
+ 'LspDiagnosticsDefaultWarning',
+ 'LspDiagnosticsFloatingError',
+ 'LspDiagnosticsFloatingHint',
+ 'LspDiagnosticsFloatingInformation',
+ 'LspDiagnosticsFloatingWarning',
+ 'LspDiagnosticsSignError',
+ 'LspDiagnosticsSignHint',
+ 'LspDiagnosticsSignInformation',
+ 'LspDiagnosticsSignWarning',
+ 'LspDiagnosticsUnderlineError',
+ 'LspDiagnosticsUnderlineHint',
+ 'LspDiagnosticsUnderlineInformation',
+ 'LspDiagnosticsUnderlineWarning',
+ 'LspDiagnosticsVirtualTextError',
+ 'LspDiagnosticsVirtualTextHint',
+ 'LspDiagnosticsVirtualTextInformation',
+ 'LspDiagnosticsVirtualTextWarning',
+ }, exec_lua([[return vim.fn.getcompletion('Lsp', 'highlight')]]))
+ end)
+
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 7df5eb049c..ef78c8db4d 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -1017,31 +1017,6 @@ describe('LSP', function()
}
end
- it('highlight groups', function()
- eq({
- 'LspDiagnosticsDefaultError',
- 'LspDiagnosticsDefaultHint',
- 'LspDiagnosticsDefaultInformation',
- 'LspDiagnosticsDefaultWarning',
- 'LspDiagnosticsFloatingError',
- 'LspDiagnosticsFloatingHint',
- 'LspDiagnosticsFloatingInformation',
- 'LspDiagnosticsFloatingWarning',
- 'LspDiagnosticsSignError',
- 'LspDiagnosticsSignHint',
- 'LspDiagnosticsSignInformation',
- 'LspDiagnosticsSignWarning',
- 'LspDiagnosticsUnderlineError',
- 'LspDiagnosticsUnderlineHint',
- 'LspDiagnosticsUnderlineInformation',
- 'LspDiagnosticsUnderlineWarning',
- 'LspDiagnosticsVirtualTextError',
- 'LspDiagnosticsVirtualTextHint',
- 'LspDiagnosticsVirtualTextInformation',
- 'LspDiagnosticsVirtualTextWarning',
- }, exec_lua([[require'vim.lsp'; return vim.fn.getcompletion('Lsp', 'highlight')]]))
- end)
-
describe('apply_text_edits', function()
before_each(function()
insert(dedent([[
diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua
index 77a41caec7..ebfd73cf85 100644
--- a/test/functional/shada/errors_spec.lua
+++ b/test/functional/shada/errors_spec.lua
@@ -342,6 +342,11 @@ describe('ShaDa error handling', function()
eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable name type', exc_exec(sdrcmd()))
end)
+ it('fails on variable item with BIN value and type value != VAR_TYPE_BLOB', function()
+ wshada('\006\000\007\147\196\001\065\196\000\000')
+ eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable type', exc_exec(sdrcmd()))
+ end)
+
it('fails on replacement item with NIL value', function()
wshada('\003\000\001\192')
eq('Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 is not an array', exc_exec(sdrcmd()))
diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua
index cc0e7fa537..854add1363 100644
--- a/test/functional/shada/variables_spec.lua
+++ b/test/functional/shada/variables_spec.lua
@@ -1,7 +1,7 @@
-- ShaDa variables saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local meths, funcs, nvim_command, eq =
- helpers.meths, helpers.funcs, helpers.command, helpers.eq
+local meths, funcs, nvim_command, eq, eval =
+ helpers.meths, helpers.funcs, helpers.command, helpers.eq, helpers.eval
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
@@ -30,10 +30,12 @@ describe('ShaDa support code', function()
else
meths.set_var(varname, varval)
end
+ local vartype = eval('type(g:' .. varname .. ')')
-- Exit during `reset` is not a regular exit: it does not write shada
-- automatically
nvim_command('qall')
reset('set shada+=!')
+ eq(vartype, eval('type(g:' .. varname .. ')'))
eq(varval, meths.get_var(varname))
end)
end
@@ -47,6 +49,8 @@ describe('ShaDa support code', function()
autotest('false', 'FALSEVAR', false)
autotest('null', 'NULLVAR', 'v:null', true)
autotest('ext', 'EXTVAR', '{"_TYPE": v:msgpack_types.ext, "_VAL": [2, ["", ""]]}', true)
+ autotest('blob', 'BLOBVAR', '0z12ab34cd', true)
+ autotest('blob (with NULs)', 'BLOBVARNULS', '0z004e554c7300', true)
it('does not read back variables without `!` in &shada', function()
meths.set_var('STRVAR', 'foo')