Mercurial > vim
changeset 26348:bf1a7ce3f14a v8.2.3705
patch 8.2.3705: cannot pass a lambda name to function() or funcref()
Commit: https://github.com/vim/vim/commit/eba3b7f6645c8f856132b4c06a009a3b0a44e21c
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Nov 30 18:25:08 2021 +0000
patch 8.2.3705: cannot pass a lambda name to function() or funcref()
Problem: Cannot pass a lambda name to function() or funcref(). (Yegappan
Lakshmanan)
Solution: Handle a lambda name differently.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 30 Nov 2021 19:30:05 +0100 |
parents | cd04fa8a6d91 |
children | 2ee2e3e3097a |
files | src/evalfunc.c src/proto/userfunc.pro src/testdir/test_expr.vim src/userfunc.c src/version.c |
diffstat | 5 files changed, 44 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3955,9 +3955,8 @@ common_function(typval_T *argvars, typva if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref) { name = s; - trans_name = trans_function_name(&name, &is_global, FALSE, - TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, - NULL, NULL, NULL); + trans_name = save_function_name(&name, &is_global, FALSE, + TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL); if (*name != NUL) s = NULL; }
--- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -33,6 +33,7 @@ int call_func(char_u *funcname, int len, char_u *printable_func_name(ufunc_T *fp); char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial, type_T **type); char_u *untrans_function_name(char_u *name); +char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, funcdict_T *fudi); void list_functions(regmatch_T *regmatch); ufunc_T *define_function(exarg_T *eap, char_u *name_arg); void ex_function(exarg_T *eap);
--- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -547,6 +547,13 @@ func Test_function_with_funcref() call assert_fails("call function('foo()')", 'E475:') call assert_fails("call function('foo()')", 'foo()') call assert_fails("function('')", 'E129:') + + let Len = {s -> strlen(s)} + call assert_equal(6, Len('foobar')) + let name = string(Len) + " can evaluate "function('<lambda>99')" + call execute('let Ref = ' .. name) + call assert_equal(4, Ref('text')) endfunc func Test_funcref()
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -3811,6 +3811,36 @@ untrans_function_name(char_u *name) } /* + * Call trans_function_name(), except that a lambda is returned as-is. + * Returns the name in allocated memory. + */ + char_u * +save_function_name( + char_u **name, + int *is_global, + int skip, + int flags, + funcdict_T *fudi) +{ + char_u *p = *name; + char_u *saved; + + if (STRNCMP(p, "<lambda>", 8) == 0) + { + p += 8; + (void)getdigits(&p); + saved = vim_strnsave(*name, p - *name); + if (fudi != NULL) + CLEAR_POINTER(fudi); + } + else + saved = trans_function_name(&p, is_global, skip, + flags, fudi, NULL, NULL); + *name = p; + return saved; +} + +/* * List functions. When "regmatch" is NULL all of then. * Otherwise functions matching "regmatch". */ @@ -3950,16 +3980,8 @@ define_function(exarg_T *eap, char_u *na } else { - if (STRNCMP(p, "<lambda>", 8) == 0) - { - p += 8; - (void)getdigits(&p); - name = vim_strnsave(eap->arg, p - eap->arg); - CLEAR_FIELD(fudi); - } - else - name = trans_function_name(&p, &is_global, eap->skip, - TFN_NO_AUTOLOAD, &fudi, NULL, NULL); + name = save_function_name(&p, &is_global, eap->skip, + TFN_NO_AUTOLOAD, &fudi); paren = (vim_strchr(p, '(') != NULL); if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) {