To: vim_dev@googlegroups.com Subject: Patch 8.2.4429 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4429 Problem: Using script-local function from the wrong script when using a partial. (Yegappan Lakshmanan) Solution: Include the script ID in the partial name. Files: src/userfunc.c, src/proto/userfunc.pro, src/evalfunc.c, src/vim9type.c, src/testdir/test_vim9_import.vim *** ../vim-8.2.4428/src/userfunc.c 2022-02-18 18:34:41.280976317 +0000 --- src/userfunc.c 2022-02-21 12:53:12.930220824 +0000 *************** *** 1958,1974 **** 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. func = find_func_with_sid(name[0] == 's' && name[1] == ':' ? name + 2 : name, current_sctx.sc_sid); if (func != NULL) return func; } } if ((flags & FFED_NO_GLOBAL) == 0) --- 1958,1986 ---- if ((flags & FFED_IS_GLOBAL) == 0) { ! // Find script-local function before global one. ! if (in_vim9script() && eval_isnamec1(*name) ! && (name[1] != ':' || *name == 's')) { 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, "", 5) == 0) + { + char_u *p = name + 5; + long sid; + + // printable "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,4073 **** --- 4080,4102 ---- } /* + * Return script-local "fname" with the 3-byte sequence replaced by + * printable 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, ""); + 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. */ *** ../vim-8.2.4428/src/proto/userfunc.pro 2022-02-12 19:52:22.024702251 +0000 --- src/proto/userfunc.pro 2022-02-21 12:17:19.437118360 +0000 *************** *** 38,43 **** --- 38,44 ---- 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); *** ../vim-8.2.4428/src/evalfunc.c 2022-02-20 18:26:43.107537899 +0000 --- src/evalfunc.c 2022-02-21 12:27:35.243609763 +0000 *************** *** 570,576 **** || 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) args[0] = &t_string; if (args[0] != NULL) args[1] = expected_ret; --- 570,576 ---- || 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_decl->tt_type == VAR_DICT) args[0] = &t_string; if (args[0] != NULL) args[1] = expected_ret; *************** *** 4366,4371 **** --- 4366,4373 ---- // 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); *** ../vim-8.2.4428/src/vim9type.c 2022-02-06 15:49:32.377256545 +0000 --- src/vim9type.c 2022-02-21 12:18:59.556879233 +0000 *************** *** 457,463 **** { type->tt_argcount -= tv->vval.v_partial->pt_argc; type->tt_min_argcount -= tv->vval.v_partial->pt_argc; ! if (type->tt_argcount == 0) type->tt_args = NULL; else { --- 457,463 ---- { type->tt_argcount -= tv->vval.v_partial->pt_argc; type->tt_min_argcount -= tv->vval.v_partial->pt_argc; ! if (type->tt_argcount <= 0) type->tt_args = NULL; else { *** ../vim-8.2.4428/src/testdir/test_vim9_import.vim 2022-02-16 21:48:20.966418934 +0000 --- src/testdir/test_vim9_import.vim 2022-02-21 12:24:50.516020383 +0000 *************** *** 423,428 **** --- 423,468 ---- 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): string + return 'found it' + enddef + + export def NewLspServer(): dict + var d: dict = {} + 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 = 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 *** ../vim-8.2.4428/src/version.c 2022-02-20 20:48:53.226071796 +0000 --- src/version.c 2022-02-21 12:25:21.143944334 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4429, /**/ -- From "know your smileys": :^[/ mean-smiley-with-cigarette /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///