Mercurial > vim
changeset 27807:292a6bd86c30 v8.2.4429
patch 8.2.4429: using script-local function from the wrong script
Commit: https://github.com/vim/vim/commit/c2f17f7e64bb1bf872dbc6f3b8f0d8751e275287
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Feb 21 13:13:50 2022 +0000
patch 8.2.4429: using script-local function from the wrong script
Problem: Using script-local function from the wrong script when using a
partial. (Yegappan Lakshmanan)
Solution: Include the script ID in the partial name.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 21 Feb 2022 14:15:04 +0100 |
parents | c8db1c5f9303 |
children | ec3ca4ad4694 |
files | src/evalfunc.c src/proto/userfunc.pro src/testdir/test_vim9_import.vim src/userfunc.c src/version.c src/vim9type.c |
diffstat | 6 files changed, 81 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -570,7 +570,7 @@ arg_map_func(type_T *type, type_T *decl_ || context->arg_types[0].type_curr->tt_type == VAR_BLOB || context->arg_types[0].type_curr->tt_type == VAR_LIST) args[0] = &t_number; - else if (context->arg_types[0].type_curr->tt_type == VAR_DICT) + else if (context->arg_types[0].type_decl->tt_type == VAR_DICT) args[0] = &t_string; if (args[0] != NULL) args[1] = expected_ret; @@ -4366,6 +4366,8 @@ common_function(typval_T *argvars, typva // would also work, but some plugins depend on the name being // printable text. name = get_scriptlocal_funcname(s); + else if (trans_name != NULL && *trans_name == K_SPECIAL) + name = alloc_printable_func_name(trans_name); else name = vim_strsave(s);
--- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -38,6 +38,7 @@ 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 *get_scriptlocal_funcname(char_u *funcname); +char_u *alloc_printable_func_name(char_u *fname); 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, garray_T *lines_to_free);
--- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -423,6 +423,46 @@ def Test_import_funcref() delete('Xlib.vim') enddef +def Test_import_duplicate_function() + # Function Hover() exists in both scripts, partial should refer to the right + # one. + var lines =<< trim END + vim9script + + def Hover(d: dict<any>): string + return 'found it' + enddef + + export def NewLspServer(): dict<any> + var d: dict<any> = {} + d->extend({hover: function('Hover', [d])}) + return d + enddef + + NewLspServer() + END + writefile(lines, 'Xserver.vim') + + lines =<< trim END + vim9script + + import './Xserver.vim' as server + + export def Hover() + enddef + + def AddServer() + var d: dict<any> = server.NewLspServer() + assert_equal('found it', d.hover()) + enddef + AddServer() + END + v9.CheckScriptSuccess(lines) + + delete('Xserver.vim') +enddef + + def Test_import_fails() writefile([], 'Xfoo.vim') var lines =<< trim END
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -1958,17 +1958,29 @@ find_func_even_dead(char_u *name, int fl if ((flags & FFED_IS_GLOBAL) == 0) { - int find_script_local = in_vim9script() && eval_isnamec1(*name) - && (name[1] != ':' || *name == 's'); - - if (find_script_local) + // Find script-local function before global one. + if (in_vim9script() && eval_isnamec1(*name) + && (name[1] != ':' || *name == 's')) { - // Find script-local function before global one. func = find_func_with_sid(name[0] == 's' && name[1] == ':' ? name + 2 : name, current_sctx.sc_sid); if (func != NULL) return func; } + if (in_vim9script() && STRNCMP(name, "<SNR>", 5) == 0) + { + char_u *p = name + 5; + long sid; + + // printable "<SNR>123_Name" form + sid = getdigits(&p); + if (*p == '_') + { + func = find_func_with_sid(p + 1, (int)sid); + if (func != NULL) + return func; + } + } } if ((flags & FFED_NO_GLOBAL) == 0) @@ -4068,6 +4080,23 @@ get_scriptlocal_funcname(char_u *funcnam } /* + * Return script-local "fname" with the 3-byte sequence replaced by + * printable <SNR> in allocated memory. + */ + char_u * +alloc_printable_func_name(char_u *fname) +{ + char_u *n = alloc(STRLEN(fname + 3) + 6); + + if (n != NULL) + { + STRCPY(n, "<SNR>"); + STRCPY(n + 5, fname + 3); + } + return n; +} + +/* * Call trans_function_name(), except that a lambda is returned as-is. * Returns the name in allocated memory. */