mirror of
https://github.com/neovim/neovim.git
synced 2025-10-02 07:58:35 +00:00
API: return non-generic VimL errors
- Return VimL errors instead of generic errors for: - nvim_call_function - nvim_call_dict_function - Fix tests which were silently broken before this change. This violates #6150 where we agreed not to translate API errors. But that can be fixed later.
This commit is contained in:
@@ -46,8 +46,7 @@
|
||||
|
||||
/// Executes an ex-command.
|
||||
///
|
||||
/// On parse error: forwards the Vim error; does not update v:errmsg.
|
||||
/// On runtime error: forwards the Vim error; does not update v:errmsg.
|
||||
/// On execution error: fails with VimL error, does not update v:errmsg.
|
||||
///
|
||||
/// @param command Ex-command string
|
||||
/// @param[out] err Error details (Vim error), if any
|
||||
@@ -103,7 +102,8 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err)
|
||||
}
|
||||
|
||||
/// Passes input keys to Nvim.
|
||||
/// On VimL error: Does not fail, but updates v:errmsg.
|
||||
///
|
||||
/// On execution error: does not fail, but updates v:errmsg.
|
||||
///
|
||||
/// @param keys to be typed
|
||||
/// @param mode mapping options
|
||||
@@ -169,7 +169,8 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
|
||||
}
|
||||
|
||||
/// Passes keys to Nvim as raw user-input.
|
||||
/// On VimL error: Does not fail, but updates v:errmsg.
|
||||
///
|
||||
/// On execution error: does not fail, but updates v:errmsg.
|
||||
///
|
||||
/// Unlike `nvim_feedkeys`, this uses a lower-level input buffer and the call
|
||||
/// is not deferred. This is the most reliable way to send real user input.
|
||||
@@ -213,8 +214,7 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
|
||||
/// Executes an ex-command and returns its (non-error) output.
|
||||
/// Shell |:!| output is not captured.
|
||||
///
|
||||
/// On parse error: forwards the Vim error; does not update v:errmsg.
|
||||
/// On runtime error: forwards the Vim error; does not update v:errmsg.
|
||||
/// On execution error: fails with VimL error, does not update v:errmsg.
|
||||
///
|
||||
/// @param command Ex-command string
|
||||
/// @param[out] err Error details (Vim error), if any
|
||||
@@ -259,7 +259,8 @@ theend:
|
||||
|
||||
/// Evaluates a VimL expression (:help expression).
|
||||
/// Dictionaries and Lists are recursively expanded.
|
||||
/// On VimL error: Returns a generic error; v:errmsg is not updated.
|
||||
///
|
||||
/// On execution error: fails with generic error; v:errmsg is not updated.
|
||||
///
|
||||
/// @param expr VimL expression string
|
||||
/// @param[out] err Error details, if any
|
||||
@@ -331,18 +332,23 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
|
||||
}
|
||||
|
||||
try_start();
|
||||
// Call the function
|
||||
msg_first_ignored_err = NULL;
|
||||
|
||||
typval_T rettv;
|
||||
int dummy;
|
||||
int r = call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size,
|
||||
vim_args, NULL, curwin->w_cursor.lnum,
|
||||
curwin->w_cursor.lnum, &dummy, true, NULL, self);
|
||||
if (r == FAIL) {
|
||||
api_set_error(err, kErrorTypeException, "Error calling function");
|
||||
// call_func() retval is deceptive; must also check did_emsg et al.
|
||||
if (msg_first_ignored_err
|
||||
&& (r == FAIL || (did_emsg && force_abort && !current_exception))) {
|
||||
api_set_error(err, kErrorTypeException, msg_first_ignored_err);
|
||||
}
|
||||
if (!try_end(err)) {
|
||||
rv = vim_to_object(&rettv);
|
||||
}
|
||||
xfree(msg_first_ignored_err);
|
||||
msg_first_ignored_err = NULL;
|
||||
tv_clear(&rettv);
|
||||
|
||||
free_vim_args:
|
||||
@@ -355,7 +361,7 @@ free_vim_args:
|
||||
|
||||
/// Calls a VimL function with the given arguments.
|
||||
///
|
||||
/// On VimL error: Returns a generic error; v:errmsg is not updated.
|
||||
/// On execution error: fails with VimL error, does not update v:errmsg.
|
||||
///
|
||||
/// @param fn Function to call
|
||||
/// @param args Function arguments packed in an Array
|
||||
@@ -369,6 +375,8 @@ Object nvim_call_function(String fn, Array args, Error *err)
|
||||
|
||||
/// Calls a VimL |Dictionary-function| with the given arguments.
|
||||
///
|
||||
/// On execution error: fails with VimL error, does not update v:errmsg.
|
||||
///
|
||||
/// @param dict Dictionary, or String evaluating to a VimL |self| dict
|
||||
/// @param fn Name of the function defined on the VimL dict
|
||||
/// @param args Function arguments packed in an Array
|
||||
|
@@ -6241,20 +6241,21 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
|
||||
/// invoked function uses them. It is called like this:
|
||||
/// new_argcount = argv_func(current_argcount, argv, called_func_argcount)
|
||||
///
|
||||
/// Return FAIL when the function can't be called, OK otherwise.
|
||||
/// Also returns OK when an error was encountered while executing the function.
|
||||
/// @return FAIL if function cannot be called, else OK (even if an error
|
||||
/// occurred while executing the function! Use `msg_first_ignored_err`
|
||||
/// to get the error)
|
||||
int
|
||||
call_func(
|
||||
const char_u *funcname, // name of the function
|
||||
int len, // length of "name"
|
||||
typval_T *rettv, // return value goes here
|
||||
typval_T *rettv, // [out] value goes here
|
||||
int argcount_in, // number of "argvars"
|
||||
typval_T *argvars_in, // vars for arguments, must have "argcount"
|
||||
// PLUS ONE elements!
|
||||
ArgvFunc argv_func, // function to fill in argvars
|
||||
linenr_T firstline, // first line of range
|
||||
linenr_T lastline, // last line of range
|
||||
int *doesrange, // return: function handled range
|
||||
int *doesrange, // [out] function handled range
|
||||
bool evaluate,
|
||||
partial_T *partial, // optional, can be NULL
|
||||
dict_T *selfdict_in // Dictionary for "self"
|
||||
@@ -6428,21 +6429,25 @@ call_func(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Give an error message with a function name. Handle <SNR> things.
|
||||
* "ermsg" is to be passed without translation, use N_() instead of _().
|
||||
*/
|
||||
/// Give an error message with a function name. Handle <SNR> things.
|
||||
///
|
||||
/// @param ermsg must be passed without translation (use N_() instead of _()).
|
||||
/// @param name function name
|
||||
static void emsg_funcname(char *ermsg, char_u *name)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *p;
|
||||
|
||||
if (*name == K_SPECIAL)
|
||||
if (*name == K_SPECIAL) {
|
||||
p = concat_str((char_u *)"<SNR>", name + 3);
|
||||
else
|
||||
} else {
|
||||
p = name;
|
||||
}
|
||||
|
||||
EMSG2(_(ermsg), p);
|
||||
if (p != name)
|
||||
|
||||
if (p != name) {
|
||||
xfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -67,6 +67,7 @@ static char_u *confirm_msg_tail; /* tail of confirm_msg */
|
||||
|
||||
MessageHistoryEntry *first_msg_hist = NULL;
|
||||
MessageHistoryEntry *last_msg_hist = NULL;
|
||||
char *msg_first_ignored_err = NULL;
|
||||
static int msg_hist_len = 0;
|
||||
|
||||
static FILE *verbose_fd = NULL;
|
||||
@@ -504,6 +505,9 @@ int emsg(const char_u *s_)
|
||||
if (cause_errthrow((char_u *)s, severe, &ignore) == true) {
|
||||
if (!ignore) {
|
||||
did_emsg = true;
|
||||
if (msg_first_ignored_err == NULL) {
|
||||
msg_first_ignored_err = xstrdup(s);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -85,6 +85,10 @@ extern MessageHistoryEntry *first_msg_hist;
|
||||
/// Last message
|
||||
extern MessageHistoryEntry *last_msg_hist;
|
||||
|
||||
/// Abort-causing non-exception error ignored by emsg(), needed by callers
|
||||
/// (RPC API) of call_func() to get error details when messages are disabled.
|
||||
extern char *msg_first_ignored_err;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "message.h.generated.h"
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user