mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.4202: Vim9: cannot export function that exists globally
Problem: Vim9: cannot export function that exists globally. Solution: When checking if a function already exists only check for script-local functions. (closes #9615)
This commit is contained in:
parent
8e4af851fd
commit
acc4b5648b
@ -8,7 +8,7 @@ char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, type_T **
|
|||||||
void emsg_funcname(char *ermsg, char_u *name);
|
void emsg_funcname(char *ermsg, char_u *name);
|
||||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
|
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
|
||||||
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
|
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
|
||||||
ufunc_T *find_func_even_dead(char_u *name, int is_global);
|
ufunc_T *find_func_even_dead(char_u *name, int flags);
|
||||||
ufunc_T *find_func(char_u *name, int is_global);
|
ufunc_T *find_func(char_u *name, int is_global);
|
||||||
int func_is_global(ufunc_T *ufunc);
|
int func_is_global(ufunc_T *ufunc);
|
||||||
int func_name_refcount(char_u *name);
|
int func_name_refcount(char_u *name);
|
||||||
|
@ -965,6 +965,37 @@ def Run_Test_import_in_spellsuggest_expr()
|
|||||||
set nospell spellsuggest& verbose=0
|
set nospell spellsuggest& verbose=0
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_export_shadows_global_function()
|
||||||
|
mkdir('Xdir/autoload', 'p')
|
||||||
|
var save_rtp = &rtp
|
||||||
|
exe 'set rtp^=' .. getcwd() .. '/Xdir'
|
||||||
|
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
export def Shadow(): string
|
||||||
|
return 'Shadow()'
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
writefile(lines, 'Xdir/autoload/shadow.vim')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
def g:Shadow(): string
|
||||||
|
return 'global'
|
||||||
|
enddef
|
||||||
|
|
||||||
|
import autoload 'shadow.vim'
|
||||||
|
assert_equal('Shadow()', shadow.Shadow())
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
delfunc g:Shadow
|
||||||
|
bwipe!
|
||||||
|
delete('Xdir', 'rf')
|
||||||
|
&rtp = save_rtp
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_export_fails()
|
def Test_export_fails()
|
||||||
CheckScriptFailure(['export var some = 123'], 'E1042:')
|
CheckScriptFailure(['export var some = 123'], 'E1042:')
|
||||||
CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
|
CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
|
||||||
|
@ -1941,16 +1941,18 @@ find_func_with_prefix(char_u *name, int sid)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a function by name, return pointer to it in ufuncs.
|
* Find a function by name, return pointer to it in ufuncs.
|
||||||
* When "is_global" is true don't find script-local or imported functions.
|
* When "flags" has FFED_IS_GLOBAL don't find script-local or imported
|
||||||
|
* functions.
|
||||||
|
* When "flags" has "FFED_NO_GLOBAL" don't find global functions.
|
||||||
* Return NULL for unknown function.
|
* Return NULL for unknown function.
|
||||||
*/
|
*/
|
||||||
ufunc_T *
|
ufunc_T *
|
||||||
find_func_even_dead(char_u *name, int is_global)
|
find_func_even_dead(char_u *name, int flags)
|
||||||
{
|
{
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
ufunc_T *func;
|
ufunc_T *func;
|
||||||
|
|
||||||
if (!is_global)
|
if ((flags & FFED_IS_GLOBAL) == 0)
|
||||||
{
|
{
|
||||||
int find_script_local = in_vim9script() && eval_isnamec1(*name)
|
int find_script_local = in_vim9script() && eval_isnamec1(*name)
|
||||||
&& (name[1] != ':' || *name == 's');
|
&& (name[1] != ':' || *name == 's');
|
||||||
@ -1965,10 +1967,13 @@ find_func_even_dead(char_u *name, int is_global)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hi = hash_find(&func_hashtab,
|
if ((flags & FFED_NO_GLOBAL) == 0)
|
||||||
|
{
|
||||||
|
hi = hash_find(&func_hashtab,
|
||||||
STRNCMP(name, "g:", 2) == 0 ? name + 2 : name);
|
STRNCMP(name, "g:", 2) == 0 ? name + 2 : name);
|
||||||
if (!HASHITEM_EMPTY(hi))
|
if (!HASHITEM_EMPTY(hi))
|
||||||
return HI2UF(hi);
|
return HI2UF(hi);
|
||||||
|
}
|
||||||
|
|
||||||
// Find autoload function if this is an autoload script.
|
// Find autoload function if this is an autoload script.
|
||||||
return find_func_with_prefix(name[0] == 's' && name[1] == ':'
|
return find_func_with_prefix(name[0] == 's' && name[1] == ':'
|
||||||
@ -1983,7 +1988,7 @@ find_func_even_dead(char_u *name, int is_global)
|
|||||||
ufunc_T *
|
ufunc_T *
|
||||||
find_func(char_u *name, int is_global)
|
find_func(char_u *name, int is_global)
|
||||||
{
|
{
|
||||||
ufunc_T *fp = find_func_even_dead(name, is_global);
|
ufunc_T *fp = find_func_even_dead(name, is_global ? FFED_IS_GLOBAL : 0);
|
||||||
|
|
||||||
if (fp != NULL && (fp->uf_flags & FC_DEAD) == 0)
|
if (fp != NULL && (fp->uf_flags & FC_DEAD) == 0)
|
||||||
return fp;
|
return fp;
|
||||||
@ -2354,7 +2359,7 @@ func_clear_free(ufunc_T *fp, int force)
|
|||||||
int
|
int
|
||||||
copy_func(char_u *lambda, char_u *global, ectx_T *ectx)
|
copy_func(char_u *lambda, char_u *global, ectx_T *ectx)
|
||||||
{
|
{
|
||||||
ufunc_T *ufunc = find_func_even_dead(lambda, TRUE);
|
ufunc_T *ufunc = find_func_even_dead(lambda, FFED_IS_GLOBAL);
|
||||||
ufunc_T *fp = NULL;
|
ufunc_T *fp = NULL;
|
||||||
|
|
||||||
if (ufunc == NULL)
|
if (ufunc == NULL)
|
||||||
@ -4464,6 +4469,7 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
|
|||||||
hashtab_T *ht;
|
hashtab_T *ht;
|
||||||
char_u *find_name = name;
|
char_u *find_name = name;
|
||||||
int var_conflict = FALSE;
|
int var_conflict = FALSE;
|
||||||
|
int ffed_flags = is_global ? FFED_IS_GLOBAL : 0;
|
||||||
|
|
||||||
v = find_var(name, &ht, TRUE);
|
v = find_var(name, &ht, TRUE);
|
||||||
if (v != NULL && (in_vim9script() || v->di_tv.v_type == VAR_FUNC))
|
if (v != NULL && (in_vim9script() || v->di_tv.v_type == VAR_FUNC))
|
||||||
@ -4481,6 +4487,9 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
|
|||||||
v = find_var(find_name, &ht, TRUE);
|
v = find_var(find_name, &ht, TRUE);
|
||||||
if (v != NULL)
|
if (v != NULL)
|
||||||
var_conflict = TRUE;
|
var_conflict = TRUE;
|
||||||
|
// Only check if the function already exists in the script,
|
||||||
|
// global functions can be shadowed.
|
||||||
|
ffed_flags |= FFED_NO_GLOBAL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4508,7 +4517,7 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
|
|||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = find_func_even_dead(find_name, is_global);
|
fp = find_func_even_dead(find_name, ffed_flags);
|
||||||
if (vim9script)
|
if (vim9script)
|
||||||
{
|
{
|
||||||
char_u *uname = untrans_function_name(name);
|
char_u *uname = untrans_function_name(name);
|
||||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
4202,
|
||||||
/**/
|
/**/
|
||||||
4201,
|
4201,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2798,4 +2798,8 @@ long elapsed(DWORD start_tick);
|
|||||||
#define VSE_SHELL 1 // escape for a shell command
|
#define VSE_SHELL 1 // escape for a shell command
|
||||||
#define VSE_BUFFER 2 // escape for a ":buffer" command
|
#define VSE_BUFFER 2 // escape for a ":buffer" command
|
||||||
|
|
||||||
|
// Flags used by find_func_even_dead()
|
||||||
|
#define FFED_IS_GLOBAL 1 // "g:" was used
|
||||||
|
#define FFED_NO_GLOBAL 2 // only check for script-local functions
|
||||||
|
|
||||||
#endif // VIM__H
|
#endif // VIM__H
|
||||||
|
@ -332,7 +332,7 @@ check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg)
|
|||||||
&& (lookup_local(p, len, NULL, cctx) == OK
|
&& (lookup_local(p, len, NULL, cctx) == OK
|
||||||
|| arg_exists(p, len, NULL, NULL, NULL, cctx) == OK))
|
|| arg_exists(p, len, NULL, NULL, NULL, cctx) == OK))
|
||||||
|| find_imported(p, len, FALSE, cctx) != NULL
|
|| find_imported(p, len, FALSE, cctx) != NULL
|
||||||
|| (ufunc = find_func_even_dead(p, FALSE)) != NULL)
|
|| (ufunc = find_func_even_dead(p, 0)) != NULL)
|
||||||
{
|
{
|
||||||
// A local or script-local function can shadow a global function.
|
// A local or script-local function can shadow a global function.
|
||||||
if (ufunc == NULL || ((ufunc->uf_flags & FC_DEAD) == 0
|
if (ufunc == NULL || ((ufunc->uf_flags & FC_DEAD) == 0
|
||||||
|
@ -2050,7 +2050,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_NEWFUNC:
|
case ISN_NEWFUNC:
|
||||||
{
|
{
|
||||||
char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
|
char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
|
||||||
ufunc_T *ufunc = find_func_even_dead(lambda, TRUE);
|
ufunc_T *ufunc = find_func_even_dead(lambda, FFED_IS_GLOBAL);
|
||||||
|
|
||||||
if (ufunc != NULL)
|
if (ufunc != NULL)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user