aboutsummaryrefslogtreecommitdiff
path: root/test/functional/lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/lua')
-rw-r--r--test/functional/lua/luaeval_spec.lua202
-rw-r--r--test/functional/lua/treesitter_spec.lua79
2 files changed, 257 insertions, 24 deletions
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 61c8e5c02e..964ea4561e 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -2,7 +2,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local redir_exec = helpers.redir_exec
local pcall_err = helpers.pcall_err
local exc_exec = helpers.exc_exec
local exec_lua = helpers.exec_lua
@@ -188,23 +187,198 @@ describe('luaeval()', function()
it('issues an error in some cases', function()
eq("Vim(call):E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys",
exc_exec('call luaeval("{1, foo=2}")'))
- eq("Vim(call):E5101: Cannot convert given lua type",
- exc_exec('call luaeval("vim.api.nvim_buf_get_lines")'))
+
startswith("Vim(call):E5107: Error loading lua [string \"luaeval()\"]:",
exc_exec('call luaeval("1, 2, 3")'))
startswith("Vim(call):E5108: Error executing lua [string \"luaeval()\"]:",
exc_exec('call luaeval("(nil)()")'))
- eq("Vim(call):E5101: Cannot convert given lua type",
- exc_exec('call luaeval("{42, vim.api}")'))
- eq("Vim(call):E5101: Cannot convert given lua type",
- exc_exec('call luaeval("{foo=42, baz=vim.api}")'))
-
- -- The following should not crash: conversion error happens inside
- eq("Vim(call):E5101: Cannot convert given lua type",
- exc_exec('call luaeval("vim.api")'))
- -- The following should not show internal error
- eq("\nE5101: Cannot convert given lua type\n0",
- redir_exec('echo luaeval("vim.api")'))
+
+ end)
+
+ it('should handle sending lua functions to viml', function()
+ eq(true, exec_lua [[
+ can_pass_lua_callback_to_vim_from_lua_result = nil
+
+ vim.fn.call(function()
+ can_pass_lua_callback_to_vim_from_lua_result = true
+ end, {})
+
+ return can_pass_lua_callback_to_vim_from_lua_result
+ ]])
+ end)
+
+ it('run functions even in timers', function()
+ eq(true, exec_lua [[
+ can_pass_lua_callback_to_vim_from_lua_result = nil
+
+ vim.fn.timer_start(50, function()
+ can_pass_lua_callback_to_vim_from_lua_result = true
+ end)
+
+ vim.wait(1000, function()
+ return can_pass_lua_callback_to_vim_from_lua_result
+ end)
+
+ return can_pass_lua_callback_to_vim_from_lua_result
+ ]])
+ end)
+
+ it('can run named functions more than once', function()
+ eq(5, exec_lua [[
+ count_of_vals = 0
+
+ vim.fn.timer_start(5, function()
+ count_of_vals = count_of_vals + 1
+ end, {['repeat'] = 5})
+
+ vim.fn.wait(1000, function()
+ return count_of_vals >= 5
+ end)
+
+ return count_of_vals
+ ]])
+ end)
+
+ it('can handle clashing names', function()
+ eq(1, exec_lua [[
+ local f_loc = function() return 1 end
+
+ local result = nil
+ vim.fn.timer_start(100, function()
+ result = f_loc()
+ end)
+
+ local f_loc = function() return 2 end
+ vim.wait(1000, function() return result ~= nil end)
+
+ return result
+ ]])
+ end)
+
+ it('should handle passing functions around', function()
+ command [[
+ function VimCanCallLuaCallbacks(Concat, Cb)
+ let message = a:Concat("Hello Vim", "I'm Lua")
+ call a:Cb(message)
+ endfunction
+ ]]
+
+ eq("Hello Vim I'm Lua", exec_lua [[
+ can_pass_lua_callback_to_vim_from_lua_result = ""
+
+ vim.fn.VimCanCallLuaCallbacks(
+ function(greeting, message) return greeting .. " " .. message end,
+ function(message) can_pass_lua_callback_to_vim_from_lua_result = message end
+ )
+
+ return can_pass_lua_callback_to_vim_from_lua_result
+ ]])
+ end)
+
+ it('should handle funcrefs', function()
+ command [[
+ function VimCanCallLuaCallbacks(Concat, Cb)
+ let message = a:Concat("Hello Vim", "I'm Lua")
+ call a:Cb(message)
+ endfunction
+ ]]
+
+ eq("Hello Vim I'm Lua", exec_lua [[
+ can_pass_lua_callback_to_vim_from_lua_result = ""
+
+ vim.funcref('VimCanCallLuaCallbacks')(
+ function(greeting, message) return greeting .. " " .. message end,
+ function(message) can_pass_lua_callback_to_vim_from_lua_result = message end
+ )
+
+ return can_pass_lua_callback_to_vim_from_lua_result
+ ]])
+ end)
+
+ it('should work with metatables using __call', function()
+ eq(1, exec_lua [[
+ local this_is_local_variable = false
+ local callable_table = setmetatable({x = 1}, {
+ __call = function(t, ...)
+ this_is_local_variable = t.x
+ end
+ })
+
+ vim.fn.timer_start(5, callable_table)
+
+ vim.wait(1000, function()
+ return this_is_local_variable
+ end)
+
+ return this_is_local_variable
+ ]])
+ end)
+
+ it('should handle being called from a timer once.', function()
+ eq(3, exec_lua [[
+ local this_is_local_variable = false
+ local callable_table = setmetatable({5, 4, 3, 2, 1}, {
+ __call = function(t, ...) this_is_local_variable = t[3] end
+ })
+
+ vim.fn.timer_start(5, callable_table)
+ vim.wait(1000, function()
+ return this_is_local_variable
+ end)
+
+ return this_is_local_variable
+ ]])
+ end)
+
+ it('should call functions once with __call metamethod', function()
+ eq(true, exec_lua [[
+ local this_is_local_variable = false
+ local callable_table = setmetatable({a = true, b = false}, {
+ __call = function(t, ...) this_is_local_variable = t.a end
+ })
+
+ assert(getmetatable(callable_table).__call)
+ vim.fn.call(callable_table, {})
+
+ return this_is_local_variable
+ ]])
+ end)
+
+ it('should work with lists using __call', function()
+ eq(3, exec_lua [[
+ local this_is_local_variable = false
+ local mt = {
+ __call = function(t, ...)
+ this_is_local_variable = t[3]
+ end
+ }
+ local callable_table = setmetatable({5, 4, 3, 2, 1}, mt)
+
+ -- Call it once...
+ vim.fn.timer_start(5, callable_table)
+ vim.wait(1000, function()
+ return this_is_local_variable
+ end)
+
+ assert(this_is_local_variable)
+ this_is_local_variable = false
+
+ vim.fn.timer_start(5, callable_table)
+ vim.wait(1000, function()
+ return this_is_local_variable
+ end)
+
+ return this_is_local_variable
+ ]])
+ end)
+
+ it('should not work with tables not using __call', function()
+ eq({false, 'Vim:E921: Invalid callback argument'}, exec_lua [[
+ local this_is_local_variable = false
+ local callable_table = setmetatable({x = 1}, {})
+
+ return {pcall(function() vim.fn.timer_start(5, callable_table) end)}
+ ]])
end)
it('correctly converts containers with type_idx', function()
diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua
index ecee471386..6ba4220849 100644
--- a/test/functional/lua/treesitter_spec.lua
+++ b/test/functional/lua/treesitter_spec.lua
@@ -237,9 +237,7 @@ static int nlua_schedule(lua_State *const lstate)
(number_literal) @number
(char_literal) @string
-; TODO(bfredl): overlapping matches are unreliable,
-; we need a proper priority mechanism
-;(type_identifier) @type
+(type_identifier) @type
((type_identifier) @Special (#eq? @Special "LuaRef"))
(primitive_type) @type
@@ -264,7 +262,7 @@ static int nlua_schedule(lua_State *const lstate)
[4] = {bold = true, foreground = Screen.colors.Brown},
[5] = {foreground = Screen.colors.Magenta},
[6] = {foreground = Screen.colors.Red},
- [7] = {foreground = Screen.colors.SlateBlue},
+ [7] = {bold = true, foreground = Screen.colors.SlateBlue},
[8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[9] = {foreground = Screen.colors.Magenta, background = Screen.colors.Red},
[10] = {foreground = Screen.colors.Red, background = Screen.colors.Red},
@@ -300,7 +298,7 @@ static int nlua_schedule(lua_State *const lstate)
]], hl_query)
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} nlua_schedule(lua_State *{3:const} lstate) |
+ {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
{ |
{4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
|| {6:lstate} != {6:lstate}) { |
@@ -311,7 +309,7 @@ static int nlua_schedule(lua_State *const lstate)
{7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
|
multiqueue_put(main_loop.events, nlua_schedule_event, |
- {5:1}, ({3:void} *)(ptrdiff_t)cb); |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
{1:~ }|
@@ -322,7 +320,7 @@ static int nlua_schedule(lua_State *const lstate)
feed('7Go*/<esc>')
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} nlua_schedule(lua_State *{3:const} lstate) |
+ {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
{ |
{4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
|| {6:lstate} != {6:lstate}) { |
@@ -334,7 +332,7 @@ static int nlua_schedule(lua_State *const lstate)
{7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
|
multiqueue_put(main_loop.events, nlua_schedule_event, |
- {5:1}, ({3:void} *)(ptrdiff_t)cb); |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
} |
{1:~ }|
@@ -344,7 +342,7 @@ static int nlua_schedule(lua_State *const lstate)
feed('3Go/*<esc>')
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} nlua_schedule(lua_State *{3:const} lstate) |
+ {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
{ |
{2:/^*} |
{2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
@@ -357,7 +355,7 @@ static int nlua_schedule(lua_State *const lstate)
{7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
|
multiqueue_put(main_loop.events, nlua_schedule_event, |
- {5:1}, ({3:void} *)(ptrdiff_t)cb); |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
{8:}} |
|
@@ -404,4 +402,65 @@ static int nlua_schedule(lua_State *const lstate)
end
eq({true,true}, {has_named,has_anonymous})
end)
+ it('allows to set simple ranges', function()
+ if not check_parser() then return end
+
+ insert(test_text)
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ return { parser:parse():root():range() }
+ ]])
+
+ eq({0, 0, 19, 0}, res)
+
+ -- The following sets the included ranges for the current parser
+ -- As stated here, this only includes the function (thus the whole buffer, without the last line)
+ local res2 = exec_lua([[
+ local root = parser:parse():root()
+ parser:set_included_ranges({root:child(0)})
+ parser.valid = false
+ return { parser:parse():root():range() }
+ ]])
+
+ eq({0, 0, 18, 1}, res2)
+ end)
+ it("allows to set complex ranges", function()
+ if not check_parser() then return end
+
+ insert(test_text)
+
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ query = vim.treesitter.parse_query("c", "(declaration) @decl")
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse():root(), 0, 0, 19) do
+ table.insert(nodes, node)
+ end
+
+ parser:set_included_ranges(nodes)
+
+ local root = parser:parse():root()
+
+ local res = {}
+ for i=0,(root:named_child_count() - 1) do
+ table.insert(res, { root:named_child(i):range() })
+ end
+ return res
+ ]])
+
+ eq({
+ { 2, 2, 2, 40 },
+ { 3, 3, 3, 32 },
+ { 4, 7, 4, 8 },
+ { 4, 8, 4, 25 },
+ { 8, 2, 8, 6 },
+ { 8, 7, 8, 33 },
+ { 9, 8, 9, 20 },
+ { 10, 4, 10, 5 },
+ { 10, 5, 10, 20 },
+ { 14, 9, 14, 27 } }, res)
+ end)
end)