1
0
forked from aniani/vim

patch 8.2.3954: Vim9: no error for shadowing if script var is declared later

Problem:    Vim9: no error for shadowing if script var is declared later.
Solution:   Check argument names when compiling a function.
This commit is contained in:
Bram Moolenaar 2021-12-31 14:06:45 +00:00
parent 6ad84ab3e4
commit 9a015111a5
4 changed files with 48 additions and 3 deletions

View File

@ -853,8 +853,8 @@ def Test_assignment_partial()
var nres: any var nres: any
var sres: any var sres: any
def Func(n: number, s = '') def Func(nr: number, s = '')
nres = n nres = nr
sres = s sres = s
enddef enddef
@ -869,7 +869,7 @@ def Test_assignment_partial()
lines =<< trim END lines =<< trim END
vim9script vim9script
def Func(n: number, s = '') def Func(nr: number, s = '')
enddef enddef
var n: number var n: number

View File

@ -951,6 +951,7 @@ def Test_call_wrong_args()
END END
CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5) CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5)
# argument name declared earlier is found when declaring a function
lines =<< trim END lines =<< trim END
vim9script vim9script
var name = 'piet' var name = 'piet'
@ -960,6 +961,17 @@ def Test_call_wrong_args()
END END
CheckScriptFailure(lines, 'E1168:') CheckScriptFailure(lines, 'E1168:')
# argument name declared later is only found when compiling
lines =<< trim END
vim9script
def FuncOne(name: string)
echo nr
enddef
var name = 'piet'
END
CheckScriptSuccess(lines)
CheckScriptFailure(lines + ['defcompile'], 'E1168:')
lines =<< trim END lines =<< trim END
vim9script vim9script
def FuncOne(nr: number) def FuncOne(nr: number)

View File

@ -749,6 +749,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 */
/**/
3954,
/**/ /**/
3953, 3953,
/**/ /**/

View File

@ -2393,6 +2393,34 @@ may_compile_assignment(exarg_T *eap, char_u **line, cctx_T *cctx)
return NOTDONE; return NOTDONE;
} }
/*
* Check if arguments of "ufunc" shadow variables in "cctx".
* Return OK or FAIL.
*/
static int
check_args_shadowing(ufunc_T *ufunc, cctx_T *cctx)
{
int i;
char_u *arg;
int r = OK;
// Make sure arguments are not found when compiling a second time.
ufunc->uf_args_visible = 0;
// Check for arguments shadowing variables from the context.
for (i = 0; i < ufunc->uf_args.ga_len; ++i)
{
arg = ((char_u **)(ufunc->uf_args.ga_data))[i];
if (check_defined(arg, STRLEN(arg), cctx, TRUE) == FAIL)
{
r = FAIL;
break;
}
}
ufunc->uf_args_visible = ufunc->uf_args.ga_len;
return r;
}
/* /*
* Add a function to the list of :def functions. * Add a function to the list of :def functions.
@ -2525,6 +2553,9 @@ compile_def_function(
estack_push_ufunc(ufunc, 1); estack_push_ufunc(ufunc, 1);
estack_compiling = TRUE; estack_compiling = TRUE;
if (check_args_shadowing(ufunc, &cctx) == FAIL)
goto erret;
if (ufunc->uf_def_args.ga_len > 0) if (ufunc->uf_def_args.ga_len > 0)
{ {
int count = ufunc->uf_def_args.ga_len; int count = ufunc->uf_def_args.ga_len;