aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2024-12-16 08:34:16 -0800
committerGitHub <noreply@github.com>2024-12-16 08:34:16 -0800
commit022449b5223659d515b78bada7de2fac8718820a (patch)
tree2ce4dd7b21d2ba4089308b877608f4dbc4166d99
parentfb8372adb3b9f50d4d18eba6f650c3728353ab00 (diff)
downloadrneovim-022449b5223659d515b78bada7de2fac8718820a.tar.gz
rneovim-022449b5223659d515b78bada7de2fac8718820a.tar.bz2
rneovim-022449b5223659d515b78bada7de2fac8718820a.zip
fix(api): generic error messages, not using TRY_WRAP #31596
Problem: - API functions using `try_start` directly, do not surface the underlying error message, and instead show generic messages. - Error-handling code is duplicated in the API impl. - Failure modes are not tested. Solution: - Use `TRY_WRAP`. - Add tests.
-rw-r--r--runtime/doc/api.txt8
-rw-r--r--runtime/lua/vim/_meta/api.lua6
-rw-r--r--src/nvim/api/vim.c35
-rw-r--r--src/nvim/api/vimscript.c24
-rw-r--r--src/nvim/api/window.c38
-rw-r--r--test/functional/api/vim_spec.lua22
-rw-r--r--test/functional/api/window_spec.lua18
-rw-r--r--test/functional/autocmd/dirchanged_spec.lua9
-rw-r--r--test/functional/lua/vim_spec.lua11
9 files changed, 92 insertions, 79 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index cb3b2a3f77..70fda5ce8a 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1647,11 +1647,9 @@ nvim_command({command}) *nvim_command()*
On execution error: fails with Vimscript error, updates v:errmsg.
- Prefer using |nvim_cmd()| or |nvim_exec2()| over this. To evaluate
- multiple lines of Vim script or an Ex command directly, use
- |nvim_exec2()|. To construct an Ex command using a structured format and
- then execute it, use |nvim_cmd()|. To modify an Ex command before
- evaluating it, use |nvim_parse_cmd()| in conjunction with |nvim_cmd()|.
+ Prefer |nvim_cmd()| or |nvim_exec2()| instead. To modify an Ex command in
+ a structured way before executing it, modify the result of
+ |nvim_parse_cmd()| then pass it to |nvim_cmd()|.
Parameters: ~
• {command} Ex command string
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index b2385197bd..55274963ed 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -885,10 +885,8 @@ function vim.api.nvim_cmd(cmd, opts) end
---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
---- Prefer using `nvim_cmd()` or `nvim_exec2()` over this. To evaluate multiple lines of Vim script
---- or an Ex command directly, use `nvim_exec2()`. To construct an Ex command using a structured
---- format and then execute it, use `nvim_cmd()`. To modify an Ex command before evaluating it, use
---- `nvim_parse_cmd()` in conjunction with `nvim_cmd()`.
+--- Prefer `nvim_cmd()` or `nvim_exec2()` instead. To modify an Ex command in a structured way
+--- before executing it, modify the result of `nvim_parse_cmd()` then pass it to `nvim_cmd()`.
---
--- @param command string Ex command string
function vim.api.nvim_command(command) end
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 1acfa0d34b..d82f90d1dd 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -669,16 +669,9 @@ void nvim_set_current_dir(String dir, Error *err)
memcpy(string, dir.data, dir.size);
string[dir.size] = NUL;
- try_start();
-
- if (!changedir_func(string, kCdScopeGlobal)) {
- if (!try_end(err)) {
- api_set_error(err, kErrorTypeException, "Failed to change directory");
- }
- return;
- }
-
- try_end(err);
+ TRY_WRAP(err, {
+ changedir_func(string, kCdScopeGlobal);
+ });
}
/// Gets the current line.
@@ -942,14 +935,9 @@ void nvim_set_current_win(Window window, Error *err)
return;
}
- try_start();
- goto_tabpage_win(win_find_tabpage(win), win);
- if (!try_end(err) && win != curwin) {
- api_set_error(err,
- kErrorTypeException,
- "Failed to switch to window %d",
- window);
- }
+ TRY_WRAP(err, {
+ goto_tabpage_win(win_find_tabpage(win), win);
+ });
}
/// Creates a new, empty, unnamed buffer.
@@ -1208,14 +1196,9 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
return;
}
- try_start();
- goto_tabpage_tp(tp, true, true);
- if (!try_end(err) && tp != curtab) {
- api_set_error(err,
- kErrorTypeException,
- "Failed to switch to tabpage %d",
- tabpage);
- }
+ TRY_WRAP(err, {
+ goto_tabpage_tp(tp, true, true);
+ });
}
/// Pastes at cursor (in any mode), and sets "redo" so dot (|.|) will repeat the input. UIs call
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index 165cc93fbe..0ff2b037ce 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -125,19 +125,17 @@ theend:
///
/// On execution error: fails with Vimscript error, updates v:errmsg.
///
-/// Prefer using |nvim_cmd()| or |nvim_exec2()| over this. To evaluate multiple lines of Vim script
-/// or an Ex command directly, use |nvim_exec2()|. To construct an Ex command using a structured
-/// format and then execute it, use |nvim_cmd()|. To modify an Ex command before evaluating it, use
-/// |nvim_parse_cmd()| in conjunction with |nvim_cmd()|.
+/// Prefer |nvim_cmd()| or |nvim_exec2()| instead. To modify an Ex command in a structured way
+/// before executing it, modify the result of |nvim_parse_cmd()| then pass it to |nvim_cmd()|.
///
/// @param command Ex command string
/// @param[out] err Error details (Vim error), if any
void nvim_command(String command, Error *err)
FUNC_API_SINCE(1)
{
- try_start();
- do_cmdline_cmd(command.data);
- try_end(err);
+ TRY_WRAP(err, {
+ do_cmdline_cmd(command.data);
+ });
}
/// Evaluates a Vimscript |expression|. Dicts and Lists are recursively expanded.
@@ -283,13 +281,11 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Arena *arena,
bool mustfree = false;
switch (dict.type) {
case kObjectTypeString:
- try_start();
- if (eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE) == FAIL) {
- api_set_error(err, kErrorTypeException,
- "Failed to evaluate dict expression");
- }
- clear_evalarg(&EVALARG_EVALUATE, NULL);
- if (try_end(err)) {
+ TRY_WRAP(err, {
+ eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE);
+ clear_evalarg(&EVALARG_EVALUATE, NULL);
+ });
+ if (ERROR_SET(err)) {
return rv;
}
// Evaluation of the string arg created a new dict or increased the
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 170d5c6cdb..f5e8d8f086 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -182,14 +182,9 @@ void nvim_win_set_height(Window window, Integer height, Error *err)
return;
}
- if (height > INT_MAX || height < INT_MIN) {
- api_set_error(err, kErrorTypeValidation, "Height value outside range");
- return;
- }
-
- try_start();
- win_setheight_win((int)height, win);
- try_end(err);
+ TRY_WRAP(err, {
+ win_setheight_win((int)height, win);
+ });
}
/// Gets the window width
@@ -224,14 +219,9 @@ void nvim_win_set_width(Window window, Integer width, Error *err)
return;
}
- if (width > INT_MAX || width < INT_MIN) {
- api_set_error(err, kErrorTypeValidation, "Width value outside range");
- return;
- }
-
- try_start();
- win_setwidth_win((int)width, win);
- try_end(err);
+ TRY_WRAP(err, {
+ win_setwidth_win((int)width, win);
+ });
}
/// Gets a window-scoped (w:) variable
@@ -436,15 +426,15 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
}
tabpage_T *tabpage = win_find_tabpage(win);
- try_start();
Object res = OBJECT_INIT;
- win_execute_T win_execute_args;
- if (win_execute_before(&win_execute_args, win, tabpage)) {
- Array args = ARRAY_DICT_INIT;
- res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
- }
- win_execute_after(&win_execute_args);
- try_end(err);
+ TRY_WRAP(err, {
+ win_execute_T win_execute_args;
+ if (win_execute_before(&win_execute_args, win, tabpage)) {
+ Array args = ARRAY_DICT_INIT;
+ res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
+ }
+ win_execute_after(&win_execute_args);
+ });
return res;
}
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 2eeb5c18a1..879df690d1 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -695,7 +695,7 @@ describe('API', function()
pcall_err(request, 'nvim_call_dict_function', 42, 'f', { 1, 2 })
)
eq(
- 'Failed to evaluate dict expression',
+ 'Vim:E121: Undefined variable: foo',
pcall_err(request, 'nvim_call_dict_function', 'foo', 'f', { 1, 2 })
)
eq('dict not found', pcall_err(request, 'nvim_call_dict_function', '42', 'f', { 1, 2 }))
@@ -1957,6 +1957,16 @@ describe('API', function()
api.nvim_set_current_win(api.nvim_list_wins()[2])
eq(api.nvim_list_wins()[2], api.nvim_get_current_win())
end)
+
+ it('failure modes', function()
+ n.command('split')
+
+ eq('Invalid window id: 9999', pcall_err(api.nvim_set_current_win, 9999))
+
+ -- XXX: force nvim_set_current_win to fail somehow.
+ n.command("au WinLeave * throw 'foo'")
+ eq('WinLeave Autocommands for "*": foo', pcall_err(api.nvim_set_current_win, 1000))
+ end)
end)
describe('nvim_{get,set}_current_tabpage, nvim_list_tabpages', function()
@@ -1976,6 +1986,16 @@ describe('API', function()
eq(api.nvim_list_tabpages()[2], api.nvim_get_current_tabpage())
eq(api.nvim_list_wins()[2], api.nvim_get_current_win())
end)
+
+ it('failure modes', function()
+ n.command('tabnew')
+
+ eq('Invalid tabpage id: 999', pcall_err(api.nvim_set_current_tabpage, 999))
+
+ -- XXX: force nvim_set_current_tabpage to fail somehow.
+ n.command("au TabLeave * throw 'foo'")
+ eq('TabLeave Autocommands for "*": foo', pcall_err(api.nvim_set_current_tabpage, 1))
+ end)
end)
describe('nvim_get_mode', function()
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 4662ace4bf..078d581b6f 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -359,6 +359,15 @@ describe('API/win', function()
eq(2, api.nvim_win_get_height(api.nvim_list_wins()[2]))
end)
+ it('failure modes', function()
+ command('split')
+ eq('Invalid window id: 999999', pcall_err(api.nvim_win_set_height, 999999, 10))
+ eq(
+ 'Wrong type for argument 2 when calling nvim_win_set_height, expecting Integer',
+ pcall_err(api.nvim_win_set_height, 0, 0.9)
+ )
+ end)
+
it('correctly handles height=1', function()
command('split')
api.nvim_set_current_win(api.nvim_list_wins()[1])
@@ -409,6 +418,15 @@ describe('API/win', function()
eq(2, api.nvim_win_get_width(api.nvim_list_wins()[2]))
end)
+ it('failure modes', function()
+ command('vsplit')
+ eq('Invalid window id: 999999', pcall_err(api.nvim_win_set_width, 999999, 10))
+ eq(
+ 'Wrong type for argument 2 when calling nvim_win_set_width, expecting Integer',
+ pcall_err(api.nvim_win_set_width, 0, 0.9)
+ )
+ end)
+
it('do not cause ml_get errors with foldmethod=expr #19989', function()
insert([[
aaaaa
diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua
index 1cde0e0552..9b572df568 100644
--- a/test/functional/autocmd/dirchanged_spec.lua
+++ b/test/functional/autocmd/dirchanged_spec.lua
@@ -351,11 +351,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
- local status, err = pcall(function()
- request('nvim_set_current_dir', '/doesnotexist')
- end)
- eq(false, status)
- eq('Failed to change directory', string.match(err, ': (.*)'))
+ eq(
+ 'Vim:E344: Can\'t find directory "/doesnotexist" in cdpath',
+ t.pcall_err(request, 'nvim_set_current_dir', '/doesnotexist')
+ )
eq({ directory = '/doesnotexist', scope = 'global', changed_window = false }, eval('g:evpre'))
eq(3, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 3cfbfe167a..9e75861aa0 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -3955,6 +3955,17 @@ stack traceback:
eq(win2, val)
end)
+ it('failure modes', function()
+ matches(
+ 'nvim_exec2%(%): Vim:E492: Not an editor command: fooooo',
+ pcall_err(exec_lua, [[vim.api.nvim_win_call(0, function() vim.cmd 'fooooo' end)]])
+ )
+ eq(
+ 'Error executing lua: [string "<nvim>"]:0: fooooo',
+ pcall_err(exec_lua, [[vim.api.nvim_win_call(0, function() error('fooooo') end)]])
+ )
+ end)
+
it('does not cause ml_get errors with invalid visual selection', function()
-- Add lines to the current buffer and make another window looking into an empty buffer.
exec_lua [[