From 86d87256c4005c6215da5af2597fbf6f6304421f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 5 Sep 2022 21:21:25 +0100 Subject: 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. --- src/errors.h | 4 ++++ src/testdir/test_user_func.vim | 25 +++++++++++++++++++++++-- src/userfunc.c | 31 ++++++++++++++++++++++++++++--- src/version.c | 2 ++ 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/errors.h b/src/errors.h index 44eb9db9f..2ed62a2af 100644 --- a/src/errors.h +++ b/src/errors.h @@ -3326,3 +3326,7 @@ EXTERN char e_non_null_list_required_for_argument_nr[] #endif EXTERN char e_window_unexpectedly_close_while_searching_for_tags[] INIT(= N_("E1299: Window unexpectedly closed while searching for tags")); +#ifdef FEAT_EVAL +EXTERN char e_cannot_use_partial_with_dictionary_for_defer[] + INIT(= N_("E1300: Cannot use a partial with dictionary for :defer")); +#endif diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim index af05812c6..4ea771119 100644 --- a/src/testdir/test_user_func.vim +++ b/src/testdir/test_user_func.vim @@ -529,8 +529,11 @@ func Test_funcdef_alloc_failure() bw! endfunc -func AddDefer(arg) - call extend(g:deferred, [a:arg]) +func AddDefer(arg1, ...) + call extend(g:deferred, [a:arg1]) + if a:0 == 1 + call extend(g:deferred, [a:1]) + endif endfunc func WithDeferTwo() @@ -550,6 +553,13 @@ func WithDeferOne() call extend(g:deferred, ['end One']) 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() let g:deferred = [] call WithDeferOne() @@ -558,6 +568,17 @@ func Test_defer() unlet g:deferred 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 diff --git a/src/userfunc.c b/src/userfunc.c index 9ac681f20..0ee276b3c 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -5567,17 +5567,42 @@ ex_call_inner( * Returns FAIL or OK. */ static int -ex_defer_inner(char_u *name, char_u **arg, evalarg_T *evalarg) +ex_defer_inner( + char_u *name, + char_u **arg, + partial_T *partial, + evalarg_T *evalarg) { 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 r; if (current_funccal == NULL) { semsg(_(e_str_not_inside_function), "defer"); 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) + { + int i; + + partial_argc = partial->pt_argc; + for (i = 0; i < partial_argc; ++i) + copy_tv(&partial->pt_argv[i], &argvars[i]); + } + } + r = get_func_arguments(arg, evalarg, FALSE, + argvars + partial_argc, &argcount); + argcount += partial_argc; + if (r == FAIL) { while (--argcount >= 0) clear_tv(&argvars[argcount]); @@ -5738,7 +5763,7 @@ ex_call(exarg_T *eap) if (eap->cmdidx == CMD_defer) { arg = startarg; - failed = ex_defer_inner(name, &arg, &evalarg) == FAIL; + failed = ex_defer_inner(name, &arg, partial, &evalarg) == FAIL; } else { diff --git a/src/version.c b/src/version.c index b114c2760..76ce3a16d 100644 --- a/src/version.c +++ b/src/version.c @@ -703,6 +703,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 390, /**/ 389, /**/ -- cgit v1.2.1