aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/generators/gen_api_dispatch.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/generators/gen_api_dispatch.lua')
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua143
1 files changed, 127 insertions, 16 deletions
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index b167767f7a..35f6bf8455 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -17,6 +17,7 @@ local nvimdir = arg[1]
package.path = nvimdir .. '/?.lua;' .. package.path
_G.vim = loadfile(nvimdir..'/../../runtime/lua/vim/shared.lua')()
+_G.vim.inspect = loadfile(nvimdir..'/../../runtime/lua/vim/inspect.lua')()
local hashy = require'generators.hashy'
@@ -59,6 +60,12 @@ for i = 6, #arg do
if public and not fn.noexport then
functions[#functions + 1] = tmp[j]
function_names[fn.name] = true
+ if #fn.parameters >= 2 and fn.parameters[2][1] == 'Array' and fn.parameters[2][2] == 'uidata' then
+ -- function receives the "args" as a parameter
+ fn.receives_array_args = true
+ -- remove the args parameter
+ table.remove(fn.parameters, 2)
+ end
if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then
-- this function should receive the channel id
fn.receives_channel_id = true
@@ -72,6 +79,15 @@ for i = 6, #arg do
-- for specifying errors
fn.parameters[#fn.parameters] = nil
end
+ if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then
+ -- return value is allocated in an arena
+ fn.arena_return = true
+ fn.parameters[#fn.parameters] = nil
+ end
+ if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'lstate' then
+ fn.has_lua_imp = true
+ fn.parameters[#fn.parameters] = nil
+ end
end
end
input:close()
@@ -149,7 +165,7 @@ local exported_attributes = {'name', 'return_type', 'method',
'since', 'deprecated_since'}
local exported_functions = {}
for _,f in ipairs(functions) do
- if not (startswith(f.name, "nvim__") or f.name == "nvim_error_event") then
+ if not (startswith(f.name, "nvim__") or f.name == "nvim_error_event" or f.name == "redraw") then
local f_exported = {}
for _,attr in ipairs(exported_attributes) do
f_exported[attr] = f[attr]
@@ -179,6 +195,35 @@ funcs_metadata_output:close()
-- start building the dispatch wrapper output
local output = io.open(dispatch_outputf, 'wb')
+
+-- ===========================================================================
+-- NEW API FILES MUST GO HERE.
+--
+-- When creating a new API file, you must include it here,
+-- so that the dispatcher can find the C functions that you are creating!
+-- ===========================================================================
+output:write([[
+#include "nvim/log.h"
+#include "nvim/map.h"
+#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/vim.h"
+
+#include "nvim/api/autocmd.h"
+#include "nvim/api/buffer.h"
+#include "nvim/api/command.h"
+#include "nvim/api/deprecated.h"
+#include "nvim/api/extmark.h"
+#include "nvim/api/options.h"
+#include "nvim/api/tabpage.h"
+#include "nvim/api/ui.h"
+#include "nvim/api/vim.h"
+#include "nvim/api/vimscript.h"
+#include "nvim/api/win_config.h"
+#include "nvim/api/window.h"
+#include "nvim/ui_client.h"
+
+]])
+
local function real_type(type)
local rv = type
local rmatch = string.match(type, "Dict%(([_%w]+)%)")
@@ -210,7 +255,7 @@ for i = 1, #functions do
if fn.impl_name == nil and fn.remote then
local args = {}
- output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)')
+ output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)')
output:write('\n{')
output:write('\n#if MIN_LOG_LEVEL <= LOGLVL_DBG')
output:write('\n logmsg(LOGLVL_DBG, "RPC: ", NULL, -1, true, "ch %" PRIu64 ": invoke '
@@ -225,11 +270,13 @@ for i = 1, #functions do
output:write('\n '..rt..' '..converted..';')
end
output:write('\n')
- output:write('\n if (args.size != '..#fn.parameters..') {')
- output:write('\n api_set_error(error, kErrorTypeException, \
- "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);')
- output:write('\n goto cleanup;')
- output:write('\n }\n')
+ if not fn.receives_array_args then
+ output:write('\n if (args.size != '..#fn.parameters..') {')
+ output:write('\n api_set_error(error, kErrorTypeException, \
+ "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);')
+ output:write('\n goto cleanup;')
+ output:write('\n }\n')
+ end
-- Validation/conversion for each argument
for j = 1, #fn.parameters do
@@ -311,12 +358,40 @@ for i = 1, #functions do
if fn.receives_channel_id then
-- if the function receives the channel id, pass it as first argument
if #args > 0 or fn.can_fail then
- output:write('channel_id, '..call_args)
+ output:write('channel_id, ')
+ if fn.receives_array_args then
+ -- if the function receives the array args, pass it the second argument
+ output:write('args, ')
+ end
+ output:write(call_args)
else
output:write('channel_id')
+ if fn.receives_array_args then
+ output:write(', args')
+ end
end
else
- output:write(call_args)
+ if fn.receives_array_args then
+ if #args > 0 or fn.call_fail then
+ output:write('args, '..call_args)
+ else
+ output:write('args')
+ end
+ else
+ output:write(call_args)
+ end
+ end
+
+ if fn.arena_return then
+ output:write(', arena')
+ end
+
+ if fn.has_lua_imp then
+ if #args > 0 then
+ output:write(', NULL')
+ else
+ output:write('NULL')
+ end
end
if fn.can_fail then
@@ -351,15 +426,18 @@ for _,fn in ipairs(functions) do
end
remote_fns.redraw = {impl_name="ui_client_redraw", fast=true}
-local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", vim.tbl_keys(remote_fns), function (idx)
+local names = vim.tbl_keys(remote_fns)
+table.sort(names)
+local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", names, function (idx)
return "method_handlers["..idx.."].name"
end)
-output:write("static const MsgpackRpcRequestHandler method_handlers[] = {\n")
-for _, name in ipairs(hashorder) do
+output:write("const MsgpackRpcRequestHandler method_handlers[] = {\n")
+for n, name in ipairs(hashorder) do
local fn = remote_fns[name]
+ fn.handler_id = n-1
output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name)..
- ', .fast = '..tostring(fn.fast)..'},\n')
+ ', .fast = '..tostring(fn.fast)..', .arena_return = '..tostring(not not fn.arena_return)..'},\n')
end
output:write("};\n\n")
output:write(hashfun)
@@ -400,6 +478,8 @@ output:write([[
#include "nvim/api/private/helpers.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
+#include "nvim/memory.h"
+
]])
include_headers(output, headers)
output:write('\n')
@@ -477,6 +557,17 @@ local function process_function(fn)
if fn.receives_channel_id then
cparams = 'LUA_INTERNAL_CALL, ' .. cparams
end
+ if fn.arena_return then
+ cparams = cparams .. '&arena, '
+ write_shifted_output(output, [[
+ Arena arena = ARENA_EMPTY;
+ ]])
+ end
+
+ if fn.has_lua_imp then
+ cparams = cparams .. 'lstate, '
+ end
+
if fn.can_fail then
cparams = cparams .. '&err'
else
@@ -511,15 +602,35 @@ local function process_function(fn)
else
return_type = fn.return_type
end
+ local free_retval
+ if fn.arena_return then
+ free_retval = "arena_mem_free(arena_finish(&arena));"
+ else
+ free_retval = "api_free_"..return_type:lower().."(ret);"
+ end
write_shifted_output(output, string.format([[
const %s ret = %s(%s);
+ ]], fn.return_type, fn.name, cparams))
+
+ if fn.has_lua_imp then
+ -- only push onto the Lua stack if we haven't already
+ write_shifted_output(output, string.format([[
+ if (lua_gettop(lstate) == 0) {
+ nlua_push_%s(lstate, ret, true);
+ }
+ ]], return_type))
+ else
+ write_shifted_output(output, string.format([[
nlua_push_%s(lstate, ret, true);
- api_free_%s(ret);
+ ]], return_type))
+ end
+
+ write_shifted_output(output, string.format([[
+ %s
%s
%s
return 1;
- ]], fn.return_type, fn.name, cparams, return_type, return_type:lower(),
- free_at_exit_code, err_throw_code))
+ ]], free_retval, free_at_exit_code, err_throw_code))
else
write_shifted_output(output, string.format([[
%s(%s);