mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 12:28:18 +00:00
feat(lua): enable stack traces in error output (#16228)
This commit is contained in:
@@ -85,6 +85,27 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
|
||||
lua_pop(lstate, 1);
|
||||
}
|
||||
|
||||
/// Like lua_pcall, but use debug.traceback as errfunc.
|
||||
///
|
||||
/// @param lstate Lua interpreter state
|
||||
/// @param[in] nargs Number of arguments expected by the function being called.
|
||||
/// @param[in] nresults Number of results the function returns.
|
||||
static int nlua_pcall(lua_State *lstate, int nargs, int nresults)
|
||||
{
|
||||
lua_getglobal(lstate, "debug");
|
||||
lua_getfield(lstate, -1, "traceback");
|
||||
lua_remove(lstate, -2);
|
||||
lua_insert(lstate, -2 - nargs);
|
||||
int status = lua_pcall(lstate, nargs, nresults, -2 - nargs);
|
||||
if (status) {
|
||||
lua_remove(lstate, -2);
|
||||
} else {
|
||||
lua_remove(lstate, -1 - nresults);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/// Gets the version of the current Nvim build.
|
||||
///
|
||||
/// @param lstate Lua interpreter state.
|
||||
@@ -115,7 +136,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags
|
||||
in_fast_callback++;
|
||||
|
||||
int top = lua_gettop(lstate);
|
||||
int status = lua_pcall(lstate, nargs, nresult, 0);
|
||||
int status = nlua_pcall(lstate, nargs, nresult);
|
||||
if (status) {
|
||||
if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) {
|
||||
// consider out of memory errors unrecoverable, just like xmalloc()
|
||||
@@ -146,7 +167,7 @@ static void nlua_schedule_event(void **argv)
|
||||
lua_State *const lstate = global_lstate;
|
||||
nlua_pushref(lstate, cb);
|
||||
nlua_unref(lstate, cb);
|
||||
if (lua_pcall(lstate, 0, 0, 0)) {
|
||||
if (nlua_pcall(lstate, 0, 0)) {
|
||||
nlua_error(lstate, _("Error executing vim.schedule lua callback: %.*s"));
|
||||
}
|
||||
}
|
||||
@@ -183,7 +204,7 @@ static void dummy_timer_close_cb(TimeWatcher *tw, void *data)
|
||||
static bool nlua_wait_condition(lua_State *lstate, int *status, bool *callback_result)
|
||||
{
|
||||
lua_pushvalue(lstate, 2);
|
||||
*status = lua_pcall(lstate, 0, 1, 0);
|
||||
*status = nlua_pcall(lstate, 0, 1);
|
||||
if (*status) {
|
||||
return true; // break on error, but keep error on stack
|
||||
}
|
||||
@@ -385,7 +406,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const char *code = (char *)&shared_module[0];
|
||||
if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/shared.lua")
|
||||
|| lua_pcall(lstate, 0, 0, 0)) {
|
||||
|| nlua_pcall(lstate, 0, 0)) {
|
||||
nlua_error(lstate, _("E5106: Error while creating shared module: %.*s"));
|
||||
return 1;
|
||||
}
|
||||
@@ -397,7 +418,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
|
||||
const char *code = (char *)&inspect_module[0];
|
||||
if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/inspect.lua")
|
||||
|| lua_pcall(lstate, 0, 1, 0)) {
|
||||
|| nlua_pcall(lstate, 0, 1)) {
|
||||
nlua_error(lstate, _("E5106: Error while creating inspect module: %.*s"));
|
||||
return 1;
|
||||
}
|
||||
@@ -406,7 +427,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
|
||||
code = (char *)&lua_F_module[0];
|
||||
if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/F.lua")
|
||||
|| lua_pcall(lstate, 0, 1, 0)) {
|
||||
|| nlua_pcall(lstate, 0, 1)) {
|
||||
nlua_error(lstate, _("E5106: Error while creating vim.F module: %.*s"));
|
||||
return 1;
|
||||
}
|
||||
@@ -419,7 +440,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const char *code = (char *)&vim_module[0];
|
||||
if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua")
|
||||
|| lua_pcall(lstate, 0, 0, 0)) {
|
||||
|| nlua_pcall(lstate, 0, 0)) {
|
||||
nlua_error(lstate, _("E5106: Error while creating vim module: %.*s"));
|
||||
return 1;
|
||||
}
|
||||
@@ -431,7 +452,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
|
||||
const char *code = (char *)&lua_meta_module[0];
|
||||
if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/_meta.lua")
|
||||
|| lua_pcall(lstate, 0, 1, 0)) {
|
||||
|| nlua_pcall(lstate, 0, 1)) {
|
||||
nlua_error(lstate, _("E5106: Error while creating vim._meta module: %.*s"));
|
||||
return 1;
|
||||
}
|
||||
@@ -549,6 +570,7 @@ static int nlua_print(lua_State *const lstate)
|
||||
for (; curargidx <= nargs; curargidx++) {
|
||||
lua_pushvalue(lstate, -1); // tostring
|
||||
lua_pushvalue(lstate, curargidx); // arg
|
||||
// Do not use nlua_pcall here to avoid duplicate stack trace information
|
||||
if (lua_pcall(lstate, 1, 1, 0)) {
|
||||
errmsg = lua_tolstring(lstate, -1, &errmsg_len);
|
||||
goto nlua_print_error;
|
||||
@@ -616,7 +638,7 @@ static int nlua_debug(lua_State *lstate)
|
||||
if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string,
|
||||
STRLEN(input.vval.v_string), "=(debug command)")) {
|
||||
nlua_error(lstate, _("E5115: Error while loading debug string: %.*s"));
|
||||
} else if (lua_pcall(lstate, 0, 0, 0)) {
|
||||
} else if (nlua_pcall(lstate, 0, 0)) {
|
||||
nlua_error(lstate, _("E5116: Error while calling debug string: %.*s"));
|
||||
}
|
||||
tv_clear(&input);
|
||||
@@ -909,7 +931,7 @@ static void nlua_typval_exec(const char *lcmd, size_t lcmd_len, const char *name
|
||||
|
||||
PUSH_ALL_TYPVALS(lstate, args, argcount, special);
|
||||
|
||||
if (lua_pcall(lstate, argcount, ret_tv ? 1 : 0, 0)) {
|
||||
if (nlua_pcall(lstate, argcount, ret_tv ? 1 : 0)) {
|
||||
nlua_error(lstate, _("E5108: Error executing lua %.*s"));
|
||||
return;
|
||||
}
|
||||
@@ -964,7 +986,7 @@ int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount
|
||||
|
||||
PUSH_ALL_TYPVALS(lstate, argvars, argcount, false);
|
||||
|
||||
if (lua_pcall(lstate, argcount, 1, 0)) {
|
||||
if (nlua_pcall(lstate, argcount, 1)) {
|
||||
nlua_print(lstate);
|
||||
return ERROR_OTHER;
|
||||
}
|
||||
@@ -999,7 +1021,7 @@ Object nlua_exec(const String str, const Array args, Error *err)
|
||||
nlua_push_Object(lstate, args.items[i], false);
|
||||
}
|
||||
|
||||
if (lua_pcall(lstate, (int)args.size, 1, 0)) {
|
||||
if (nlua_pcall(lstate, (int)args.size, 1)) {
|
||||
size_t len;
|
||||
const char *errstr = lua_tolstring(lstate, -1, &len);
|
||||
api_set_error(err, kErrorTypeException,
|
||||
@@ -1032,7 +1054,7 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro
|
||||
nlua_push_Object(lstate, args.items[i], false);
|
||||
}
|
||||
|
||||
if (lua_pcall(lstate, nargs, retval ? 1 : 0, 0)) {
|
||||
if (nlua_pcall(lstate, nargs, retval ? 1 : 0)) {
|
||||
// if err is passed, the caller will deal with the error.
|
||||
if (err) {
|
||||
size_t len;
|
||||
@@ -1126,7 +1148,7 @@ void ex_luado(exarg_T *const eap)
|
||||
if (lcmd_len >= IOSIZE) {
|
||||
xfree(lcmd);
|
||||
}
|
||||
if (lua_pcall(lstate, 0, 1, 0)) {
|
||||
if (nlua_pcall(lstate, 0, 1)) {
|
||||
nlua_error(lstate, _("E5110: Error executing lua: %.*s"));
|
||||
return;
|
||||
}
|
||||
@@ -1138,7 +1160,7 @@ void ex_luado(exarg_T *const eap)
|
||||
const char *old_line = (const char *)ml_get_buf(curbuf, l, false);
|
||||
lua_pushstring(lstate, old_line);
|
||||
lua_pushnumber(lstate, (lua_Number)l);
|
||||
if (lua_pcall(lstate, 2, 1, 0)) {
|
||||
if (nlua_pcall(lstate, 2, 1)) {
|
||||
nlua_error(lstate, _("E5111: Error calling lua: %.*s"));
|
||||
break;
|
||||
}
|
||||
@@ -1189,7 +1211,7 @@ bool nlua_exec_file(const char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lua_pcall(lstate, 0, 0, 0)) {
|
||||
if (nlua_pcall(lstate, 0, 0)) {
|
||||
nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s"));
|
||||
return false;
|
||||
}
|
||||
@@ -1241,7 +1263,7 @@ int nlua_expand_pat(expand_T *xp, char_u *pat, int *num_results, char_u ***resul
|
||||
// [ vim, vim._on_key, buf ]
|
||||
lua_pushlstring(lstate, (const char *)pat, STRLEN(pat));
|
||||
|
||||
if (lua_pcall(lstate, 1, 2, 0) != 0) {
|
||||
if (nlua_pcall(lstate, 1, 2) != 0) {
|
||||
nlua_error(lstate,
|
||||
_("Error executing vim._expand_pat: %.*s"));
|
||||
return FAIL;
|
||||
@@ -1394,7 +1416,7 @@ void nlua_execute_on_key(int c)
|
||||
// [ vim, vim._on_key, buf ]
|
||||
lua_pushlstring(lstate, (const char *)buf, buf_len);
|
||||
|
||||
if (lua_pcall(lstate, 1, 0, 0)) {
|
||||
if (nlua_pcall(lstate, 1, 0)) {
|
||||
nlua_error(lstate,
|
||||
_("Error executing vim.on_key Lua callback: %.*s"));
|
||||
}
|
||||
|
Reference in New Issue
Block a user