mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-patch:9.0.0390: cannot use a partial with :defer
Problem: Cannot use a partial with :defer.
Solution: Add the partial arguments before the other arguments. Disallow
using a dictionary.
86d87256c4
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -406,7 +406,8 @@ GetArg()->TheFunc()` does not work, it may work in a later version.
|
|||||||
|
|
||||||
Errors are reported but do not cause aborting execution of deferred functions.
|
Errors are reported but do not cause aborting execution of deferred functions.
|
||||||
|
|
||||||
No range is accepted.
|
No range is accepted. The function can be a partial with extra arguments, but
|
||||||
|
not with a dictionary. *E1300*
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
|
@@ -81,6 +81,8 @@ static const char e_no_white_space_allowed_before_str_str[]
|
|||||||
= N_("E1068: No white space allowed before '%s': %s");
|
= N_("E1068: No white space allowed before '%s': %s");
|
||||||
static const char e_missing_heredoc_end_marker_str[]
|
static const char e_missing_heredoc_end_marker_str[]
|
||||||
= N_("E1145: Missing heredoc end marker: %s");
|
= N_("E1145: Missing heredoc end marker: %s");
|
||||||
|
static const char e_cannot_use_partial_with_dictionary_for_defer[]
|
||||||
|
= N_("E1300: Cannot use a partial with dictionary for :defer");
|
||||||
|
|
||||||
void func_init(void)
|
void func_init(void)
|
||||||
{
|
{
|
||||||
@@ -3062,7 +3064,7 @@ void ex_return(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg,
|
static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg,
|
||||||
funcexe_T *funcexe_init, evalarg_T *const evalarg)
|
const funcexe_T *const funcexe_init, evalarg_T *const evalarg)
|
||||||
{
|
{
|
||||||
bool doesrange;
|
bool doesrange;
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
@@ -3116,16 +3118,32 @@ static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg,
|
|||||||
/// Core part of ":defer func(arg)". "arg" points to the "(" and is advanced.
|
/// Core part of ":defer func(arg)". "arg" points to the "(" and is advanced.
|
||||||
///
|
///
|
||||||
/// @return FAIL or OK.
|
/// @return FAIL or OK.
|
||||||
static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg)
|
static int ex_defer_inner(char *name, char **arg, const partial_T *const partial,
|
||||||
|
evalarg_T *const evalarg)
|
||||||
{
|
{
|
||||||
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
|
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
|
||||||
|
int partial_argc = 0; // number of partial arguments
|
||||||
int argcount = 0; // number of arguments found
|
int argcount = 0; // number of arguments found
|
||||||
|
|
||||||
if (current_funccal == NULL) {
|
if (current_funccal == NULL) {
|
||||||
semsg(_(e_str_not_inside_function), "defer");
|
semsg(_(e_str_not_inside_function), "defer");
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (get_func_arguments(arg, evalarg, false, argvars, &argcount) == FAIL) {
|
if (partial != NULL) {
|
||||||
|
if (partial->pt_dict != NULL) {
|
||||||
|
emsg(_(e_cannot_use_partial_with_dictionary_for_defer));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (partial->pt_argc > 0) {
|
||||||
|
partial_argc = partial->pt_argc;
|
||||||
|
for (int i = 0; i < partial_argc; i++) {
|
||||||
|
tv_copy(&partial->pt_argv[i], &argvars[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int r = get_func_arguments(arg, evalarg, false, argvars + partial_argc, &argcount);
|
||||||
|
argcount += partial_argc;
|
||||||
|
if (r == FAIL) {
|
||||||
while (--argcount >= 0) {
|
while (--argcount >= 0) {
|
||||||
tv_clear(&argvars[argcount]);
|
tv_clear(&argvars[argcount]);
|
||||||
}
|
}
|
||||||
@@ -3236,7 +3254,7 @@ void ex_call(exarg_T *eap)
|
|||||||
|
|
||||||
if (eap->cmdidx == CMD_defer) {
|
if (eap->cmdidx == CMD_defer) {
|
||||||
arg = startarg;
|
arg = startarg;
|
||||||
failed = ex_defer_inner(name, &arg, &evalarg) == FAIL;
|
failed = ex_defer_inner(name, &arg, partial, &evalarg) == FAIL;
|
||||||
} else {
|
} else {
|
||||||
funcexe_T funcexe = FUNCEXE_INIT;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
funcexe.fe_partial = partial;
|
funcexe.fe_partial = partial;
|
||||||
|
@@ -532,8 +532,11 @@ func Test_funcdef_alloc_failure()
|
|||||||
bw!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func AddDefer(arg)
|
func AddDefer(arg1, ...)
|
||||||
call extend(g:deferred, [a:arg])
|
call extend(g:deferred, [a:arg1])
|
||||||
|
if a:0 == 1
|
||||||
|
call extend(g:deferred, [a:1])
|
||||||
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func WithDeferTwo()
|
func WithDeferTwo()
|
||||||
@@ -553,6 +556,13 @@ func WithDeferOne()
|
|||||||
call extend(g:deferred, ['end One'])
|
call extend(g:deferred, ['end One'])
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func WithPartialDefer()
|
||||||
|
call extend(g:deferred, ['in Partial'])
|
||||||
|
let Part = funcref('AddDefer', ['arg1'])
|
||||||
|
defer Part("arg2")
|
||||||
|
call extend(g:deferred, ['end Partial'])
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_defer()
|
func Test_defer()
|
||||||
let g:deferred = []
|
let g:deferred = []
|
||||||
call WithDeferOne()
|
call WithDeferOne()
|
||||||
@@ -561,6 +571,17 @@ func Test_defer()
|
|||||||
unlet g:deferred
|
unlet g:deferred
|
||||||
|
|
||||||
call assert_equal('', glob('Xfuncdefer'))
|
call assert_equal('', glob('Xfuncdefer'))
|
||||||
|
|
||||||
|
call assert_fails('defer delete("Xfuncdefer")->Another()', 'E488:')
|
||||||
|
call assert_fails('defer delete("Xfuncdefer").member', 'E488:')
|
||||||
|
|
||||||
|
let g:deferred = []
|
||||||
|
call WithPartialDefer()
|
||||||
|
call assert_equal(['in Partial', 'end Partial', 'arg1', 'arg2'], g:deferred)
|
||||||
|
unlet g:deferred
|
||||||
|
|
||||||
|
let Part = funcref('AddDefer', ['arg1'], {})
|
||||||
|
call assert_fails('defer Part("arg2")', 'E1300:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user