From 103ddaf9ae80a32e50325888b0cde1c4354f8413 Mon Sep 17 00:00:00 2001 From: Tommy Guo Date: Tue, 20 Jan 2026 21:18:33 -0500 Subject: [PATCH] fix(lua): correct line number reporting for options set in coroutines (#37463) --- src/gen/gen_api_dispatch.lua | 4 ++++ src/nvim/lua/executor.c | 7 ++++++- src/nvim/lua/executor.h | 10 ++++++++++ test/functional/ex_cmds/verbose_spec.lua | 17 +++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/gen/gen_api_dispatch.lua b/src/gen/gen_api_dispatch.lua index 9ee666b003..0b33f2ce9a 100644 --- a/src/gen/gen_api_dispatch.lua +++ b/src/gen/gen_api_dispatch.lua @@ -840,6 +840,8 @@ local function process_function(fn) else cparams = cparams:gsub(', $', '') end + + write_shifted_output(' ENTER_LUA_ACTIVE_STATE(lstate);\n') local free_at_exit_code = '' for i = 1, #free_code do local rev_i = #free_code - i + 1 @@ -903,6 +905,7 @@ exit_0: -- NOTE: we currently assume err_throw needs nothing from arena write_shifted_output( [[ + LEAVE_LUA_ACTIVE_STATE(); %s %s %s @@ -916,6 +919,7 @@ exit_0: write_shifted_output( [[ %s(%s); + LEAVE_LUA_ACTIVE_STATE(); %s %s return 0; diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 181a549e23..e047c051f7 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -81,6 +81,9 @@ static bool in_script = false; // Initialized in nlua_init(). static lua_State *global_lstate = NULL; +// Tracks the currently executing Lua thread (main or coroutine). +lua_State *active_lstate = NULL; + static LuaRef require_ref = LUA_REFNIL; static uv_thread_t main_thread; @@ -883,6 +886,7 @@ void nlua_init(char **argv, int argc, int lua_arg0) luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem); global_lstate = lstate; + active_lstate = lstate; main_thread = uv_thread_self(); nlua_init_argv(lstate, argv, argc, lua_arg0); } @@ -1484,6 +1488,7 @@ static void nlua_typval_exec(const char *lcmd, size_t lcmd_len, const char *name } lua_State *const lstate = global_lstate; + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, name)) { nlua_error(lstate, _("E5107: Lua: %.*s")); return; @@ -2131,7 +2136,7 @@ void nlua_set_sctx(sctx_T *current) if (p_verbose <= 0) { return; } - lua_State *const lstate = global_lstate; + lua_State *const lstate = active_lstate; lua_Debug *info = (lua_Debug *)xmalloc(sizeof(lua_Debug)); // Files where internal wrappers are defined so we can ignore them diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h index 9448c4a220..88acf2dece 100644 --- a/src/nvim/lua/executor.h +++ b/src/nvim/lua/executor.h @@ -55,3 +55,13 @@ enum { CB_MAX_ERROR = 3, }; EXTERN nlua_ref_state_t *nlua_global_refs INIT( = NULL); EXTERN bool nlua_disable_preload INIT( = false); + +/// Tracks the active Lua thread +extern lua_State *active_lstate; + +#define ENTER_LUA_ACTIVE_STATE(new_state) \ + lua_State *const save_active_lstate = active_lstate; \ + active_lstate = (new_state); + +#define LEAVE_LUA_ACTIVE_STATE() \ + active_lstate = save_active_lstate; diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua index faddab1e42..67ce9d894c 100644 --- a/test/functional/ex_cmds/verbose_spec.lua +++ b/test/functional/ex_cmds/verbose_spec.lua @@ -80,6 +80,10 @@ local set_list = ([[ vim.api.nvim_exec2(set_list, {}) vim.api.nvim_create_autocmd('User', { pattern = 'set_mouse', callback = cb }) + +coroutine.wrap(function() + vim.o.busy = 2 +end)() ]=] ) exec(cmd .. ' ' .. script_file) @@ -281,6 +285,19 @@ TestHL2 xxx guibg=Green result ) end) + + it('for option set in coroutine', function() + local result = exec_capture(':verbose set busy?') + eq( + string.format( + [[ + busy=2 + Last set from %s]], + get_last_set_location(59) + ), + result + ) + end) end describe('lua :verbose with -V1', function()