diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-04-16 10:51:27 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-04-16 15:04:41 +0800 |
commit | 335bef0c211dc962499814d248670ff17758a642 (patch) | |
tree | 808c44bc0f507ad155927b41596a0408d0559a8d | |
parent | 0167649ce4071e60d985b65f3f9408ffb21cb58c (diff) | |
download | rneovim-335bef0c211dc962499814d248670ff17758a642.tar.gz rneovim-335bef0c211dc962499814d248670ff17758a642.tar.bz2 rneovim-335bef0c211dc962499814d248670ff17758a642.zip |
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.
https://github.com/vim/vim/commit/86d87256c4005c6215da5af2597fbf6f6304421f
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | runtime/doc/userfunc.txt | 3 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 26 | ||||
-rw-r--r-- | test/old/testdir/test_user_func.vim | 25 |
3 files changed, 47 insertions, 7 deletions
diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt index 2c72f3d584..db0127df95 100644 --- a/runtime/doc/userfunc.txt +++ b/runtime/doc/userfunc.txt @@ -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. -No range is accepted. +No range is accepted. The function can be a partial with extra arguments, but +not with a dictionary. *E1300* ============================================================================== diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 4b9bc1fdec..e9e780747a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -81,6 +81,8 @@ static const char e_no_white_space_allowed_before_str_str[] = N_("E1068: No white space allowed before '%s': %s"); static const char e_missing_heredoc_end_marker_str[] = 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) { @@ -3062,7 +3064,7 @@ void ex_return(exarg_T *eap) } 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 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. /// /// @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 + int partial_argc = 0; // number of partial arguments int argcount = 0; // number of arguments found 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) { + 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) { tv_clear(&argvars[argcount]); } @@ -3236,7 +3254,7 @@ void 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 { funcexe_T funcexe = FUNCEXE_INIT; funcexe.fe_partial = partial; diff --git a/test/old/testdir/test_user_func.vim b/test/old/testdir/test_user_func.vim index 3579954fe6..fd70d1acb0 100644 --- a/test/old/testdir/test_user_func.vim +++ b/test/old/testdir/test_user_func.vim @@ -532,8 +532,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() @@ -553,6 +556,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() @@ -561,6 +571,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 |