mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.4332: Vim9: incomplete test for existing script variable in block
Problem: Vim9: incomplete test for existing script variable in block. Solution: Add a couple more tests. Fix uncovered problem.
This commit is contained in:
@@ -2,8 +2,8 @@
|
|||||||
int lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx);
|
int lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx);
|
||||||
int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int *gen_load_outer, cctx_T *cctx);
|
int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int *gen_load_outer, cctx_T *cctx);
|
||||||
int script_is_vim9(void);
|
int script_is_vim9(void);
|
||||||
int script_var_exists(char_u *name, size_t len, cctx_T *cctx);
|
int script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack);
|
||||||
int check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg);
|
int check_defined(char_u *p, size_t len, cctx_T *cctx, cstack_T *cstack, int is_arg);
|
||||||
int need_type_where(type_T *actual, type_T *expected, int offset, where_T where, cctx_T *cctx, int silent, int actual_is_const);
|
int need_type_where(type_T *actual, type_T *expected, int offset, where_T where, cctx_T *cctx, int silent, int actual_is_const);
|
||||||
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
|
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
|
||||||
lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type);
|
lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type);
|
||||||
|
@@ -1057,6 +1057,43 @@ def Test_call_wrong_args()
|
|||||||
END
|
END
|
||||||
v9.CheckScriptSuccess(lines)
|
v9.CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
# with another variable in another block
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
if true
|
||||||
|
var name = 'piet'
|
||||||
|
# define a function so that the variable isn't cleared
|
||||||
|
def GetItem(): string
|
||||||
|
return item
|
||||||
|
enddef
|
||||||
|
endif
|
||||||
|
if true
|
||||||
|
var name = 'peter'
|
||||||
|
def FuncOne(name: string)
|
||||||
|
echo name
|
||||||
|
enddef
|
||||||
|
endif
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1168:')
|
||||||
|
|
||||||
|
# only variable in another block is OK
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
if true
|
||||||
|
var name = 'piet'
|
||||||
|
# define a function so that the variable isn't cleared
|
||||||
|
def GetItem(): string
|
||||||
|
return item
|
||||||
|
enddef
|
||||||
|
endif
|
||||||
|
if true
|
||||||
|
def FuncOne(name: string)
|
||||||
|
echo name
|
||||||
|
enddef
|
||||||
|
endif
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
|
||||||
# argument name declared later is only found when compiling
|
# argument name declared later is only found when compiling
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
@@ -55,6 +55,7 @@ func_tbl_get(void)
|
|||||||
* If "argtypes" is not NULL also get the type: "arg: type" (:def function).
|
* If "argtypes" is not NULL also get the type: "arg: type" (:def function).
|
||||||
* If "types_optional" is TRUE a missing type is OK, use "any".
|
* If "types_optional" is TRUE a missing type is OK, use "any".
|
||||||
* If "evalarg" is not NULL use it to check for an already declared name.
|
* If "evalarg" is not NULL use it to check for an already declared name.
|
||||||
|
* If "eap" is not NULL use it to check for an already declared name.
|
||||||
* Return a pointer to after the type.
|
* Return a pointer to after the type.
|
||||||
* When something is wrong return "arg".
|
* When something is wrong return "arg".
|
||||||
*/
|
*/
|
||||||
@@ -65,6 +66,7 @@ one_function_arg(
|
|||||||
garray_T *argtypes,
|
garray_T *argtypes,
|
||||||
int types_optional,
|
int types_optional,
|
||||||
evalarg_T *evalarg,
|
evalarg_T *evalarg,
|
||||||
|
exarg_T *eap,
|
||||||
int is_vararg,
|
int is_vararg,
|
||||||
int skip)
|
int skip)
|
||||||
{
|
{
|
||||||
@@ -87,7 +89,8 @@ one_function_arg(
|
|||||||
// Vim9 script: cannot use script var name for argument. In function: also
|
// Vim9 script: cannot use script var name for argument. In function: also
|
||||||
// check local vars and arguments.
|
// check local vars and arguments.
|
||||||
if (!skip && argtypes != NULL && check_defined(arg, p - arg,
|
if (!skip && argtypes != NULL && check_defined(arg, p - arg,
|
||||||
evalarg == NULL ? NULL : evalarg->eval_cctx, TRUE) == FAIL)
|
evalarg == NULL ? NULL : evalarg->eval_cctx,
|
||||||
|
eap == NULL ? NULL : eap->cstack, TRUE) == FAIL)
|
||||||
return arg;
|
return arg;
|
||||||
|
|
||||||
if (newargs != NULL && ga_grow(newargs, 1) == FAIL)
|
if (newargs != NULL && ga_grow(newargs, 1) == FAIL)
|
||||||
@@ -210,7 +213,7 @@ get_function_args(
|
|||||||
int *varargs,
|
int *varargs,
|
||||||
garray_T *default_args,
|
garray_T *default_args,
|
||||||
int skip,
|
int skip,
|
||||||
exarg_T *eap,
|
exarg_T *eap, // can be NULL
|
||||||
garray_T *lines_to_free)
|
garray_T *lines_to_free)
|
||||||
{
|
{
|
||||||
int mustend = FALSE;
|
int mustend = FALSE;
|
||||||
@@ -279,7 +282,7 @@ get_function_args(
|
|||||||
|
|
||||||
arg = p;
|
arg = p;
|
||||||
p = one_function_arg(p, newargs, argtypes, types_optional,
|
p = one_function_arg(p, newargs, argtypes, types_optional,
|
||||||
evalarg, TRUE, skip);
|
evalarg, eap, TRUE, skip);
|
||||||
if (p == arg)
|
if (p == arg)
|
||||||
break;
|
break;
|
||||||
if (*skipwhite(p) == '=')
|
if (*skipwhite(p) == '=')
|
||||||
@@ -295,7 +298,7 @@ get_function_args(
|
|||||||
|
|
||||||
arg = p;
|
arg = p;
|
||||||
p = one_function_arg(p, newargs, argtypes, types_optional,
|
p = one_function_arg(p, newargs, argtypes, types_optional,
|
||||||
evalarg, FALSE, skip);
|
evalarg, eap, FALSE, skip);
|
||||||
if (p == arg)
|
if (p == arg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@@ -746,6 +746,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 */
|
||||||
|
/**/
|
||||||
|
4332,
|
||||||
/**/
|
/**/
|
||||||
4331,
|
4331,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -152,11 +152,12 @@ arg_exists(
|
|||||||
* Lookup a script-local variable in the current script, possibly defined in a
|
* Lookup a script-local variable in the current script, possibly defined in a
|
||||||
* block that contains the function "cctx->ctx_ufunc".
|
* block that contains the function "cctx->ctx_ufunc".
|
||||||
* "cctx" is NULL at the script level.
|
* "cctx" is NULL at the script level.
|
||||||
|
* "cstack_T" is NULL in a function.
|
||||||
* If "len" is <= 0 "name" must be NUL terminated.
|
* If "len" is <= 0 "name" must be NUL terminated.
|
||||||
* Return NULL when not found.
|
* Return NULL when not found.
|
||||||
*/
|
*/
|
||||||
static sallvar_T *
|
static sallvar_T *
|
||||||
find_script_var(char_u *name, size_t len, cctx_T *cctx)
|
find_script_var(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
|
||||||
{
|
{
|
||||||
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
|
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
@@ -183,11 +184,22 @@ find_script_var(char_u *name, size_t len, cctx_T *cctx)
|
|||||||
|
|
||||||
if (cctx == NULL)
|
if (cctx == NULL)
|
||||||
{
|
{
|
||||||
// Not in a function scope, find variable with block id equal to or
|
// Not in a function scope, find variable with block ID equal to or
|
||||||
// smaller than the current block id.
|
// smaller than the current block id. If "cstack" is not NULL go up
|
||||||
|
// the block scopes (more accurate).
|
||||||
while (sav != NULL)
|
while (sav != NULL)
|
||||||
{
|
{
|
||||||
if (sav->sav_block_id <= si->sn_current_block_id)
|
if (cstack != NULL)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = cstack->cs_idx; idx >= 0; --idx)
|
||||||
|
if (cstack->cs_block_id[idx] == sav->sav_block_id)
|
||||||
|
break;
|
||||||
|
if (idx >= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (sav->sav_block_id <= si->sn_current_block_id)
|
||||||
break;
|
break;
|
||||||
sav = sav->sav_next;
|
sav = sav->sav_next;
|
||||||
}
|
}
|
||||||
@@ -225,10 +237,11 @@ script_is_vim9()
|
|||||||
/*
|
/*
|
||||||
* Lookup a variable (without s: prefix) in the current script.
|
* Lookup a variable (without s: prefix) in the current script.
|
||||||
* "cctx" is NULL at the script level.
|
* "cctx" is NULL at the script level.
|
||||||
|
* "cstack" is NULL in a function.
|
||||||
* Returns OK or FAIL.
|
* Returns OK or FAIL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
script_var_exists(char_u *name, size_t len, cctx_T *cctx)
|
script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
|
||||||
{
|
{
|
||||||
if (current_sctx.sc_sid <= 0)
|
if (current_sctx.sc_sid <= 0)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -236,7 +249,7 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx)
|
|||||||
{
|
{
|
||||||
// Check script variables that were visible where the function was
|
// Check script variables that were visible where the function was
|
||||||
// defined.
|
// defined.
|
||||||
if (find_script_var(name, len, cctx) != NULL)
|
if (find_script_var(name, len, cctx, cstack) != NULL)
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -267,7 +280,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
|
|||||||
return (cctx != NULL
|
return (cctx != NULL
|
||||||
&& (lookup_local(name, len, NULL, cctx) == OK
|
&& (lookup_local(name, len, NULL, cctx) == OK
|
||||||
|| arg_exists(name, len, NULL, NULL, NULL, cctx) == OK))
|
|| arg_exists(name, len, NULL, NULL, NULL, cctx) == OK))
|
||||||
|| script_var_exists(name, len, cctx) == OK
|
|| script_var_exists(name, len, cctx, NULL) == OK
|
||||||
|| find_imported(name, len, FALSE, cctx) != NULL;
|
|| find_imported(name, len, FALSE, cctx) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +322,12 @@ item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx)
|
|||||||
* Return FAIL and give an error if it defined.
|
* Return FAIL and give an error if it defined.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg)
|
check_defined(
|
||||||
|
char_u *p,
|
||||||
|
size_t len,
|
||||||
|
cctx_T *cctx,
|
||||||
|
cstack_T *cstack,
|
||||||
|
int is_arg)
|
||||||
{
|
{
|
||||||
int c = p[len];
|
int c = p[len];
|
||||||
ufunc_T *ufunc = NULL;
|
ufunc_T *ufunc = NULL;
|
||||||
@@ -318,7 +336,7 @@ check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg)
|
|||||||
if (len == 1 && *p == '_')
|
if (len == 1 && *p == '_')
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
if (script_var_exists(p, len, cctx) == OK)
|
if (script_var_exists(p, len, cctx, cstack) == OK)
|
||||||
{
|
{
|
||||||
if (is_arg)
|
if (is_arg)
|
||||||
semsg(_(e_argument_already_declared_in_script_str), p);
|
semsg(_(e_argument_already_declared_in_script_str), p);
|
||||||
@@ -526,7 +544,7 @@ get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
|
|||||||
return -1;
|
return -1;
|
||||||
if (sid == current_sctx.sc_sid)
|
if (sid == current_sctx.sc_sid)
|
||||||
{
|
{
|
||||||
sallvar_T *sav = find_script_var(name, 0, cctx);
|
sallvar_T *sav = find_script_var(name, 0, cctx, NULL);
|
||||||
|
|
||||||
if (sav == NULL)
|
if (sav == NULL)
|
||||||
return -2;
|
return -2;
|
||||||
@@ -884,7 +902,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
|
|||||||
semsg(_(e_namespace_not_supported_str), name_start);
|
semsg(_(e_namespace_not_supported_str), name_start);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (check_defined(name_start, name_end - name_start, cctx, FALSE) == FAIL)
|
if (check_defined(name_start, name_end - name_start, cctx,
|
||||||
|
NULL, FALSE) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!ASCII_ISUPPER(is_global ? name_start[2] : name_start[0]))
|
if (!ASCII_ISUPPER(is_global ? name_start[2] : name_start[0]))
|
||||||
{
|
{
|
||||||
@@ -1356,9 +1375,9 @@ compile_lhs(
|
|||||||
&& STRNCMP(var_start, "s:", 2) == 0;
|
&& STRNCMP(var_start, "s:", 2) == 0;
|
||||||
int script_var = (script_namespace
|
int script_var = (script_namespace
|
||||||
? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
|
? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
|
||||||
cctx)
|
cctx, NULL)
|
||||||
: script_var_exists(var_start, lhs->lhs_varlen,
|
: script_var_exists(var_start, lhs->lhs_varlen,
|
||||||
cctx)) == OK;
|
cctx, NULL)) == OK;
|
||||||
imported_T *import =
|
imported_T *import =
|
||||||
find_imported(var_start, lhs->lhs_varlen, FALSE, cctx);
|
find_imported(var_start, lhs->lhs_varlen, FALSE, cctx);
|
||||||
|
|
||||||
@@ -1442,8 +1461,8 @@ compile_lhs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (check_defined(var_start, lhs->lhs_varlen, cctx, FALSE)
|
else if (check_defined(var_start, lhs->lhs_varlen, cctx,
|
||||||
== FAIL)
|
NULL, FALSE) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2470,7 +2489,7 @@ check_args_shadowing(ufunc_T *ufunc, cctx_T *cctx)
|
|||||||
for (i = 0; i < ufunc->uf_args.ga_len; ++i)
|
for (i = 0; i < ufunc->uf_args.ga_len; ++i)
|
||||||
{
|
{
|
||||||
arg = ((char_u **)(ufunc->uf_args.ga_data))[i];
|
arg = ((char_u **)(ufunc->uf_args.ga_data))[i];
|
||||||
if (check_defined(arg, STRLEN(arg), cctx, TRUE) == FAIL)
|
if (check_defined(arg, STRLEN(arg), cctx, NULL, TRUE) == FAIL)
|
||||||
{
|
{
|
||||||
r = FAIL;
|
r = FAIL;
|
||||||
break;
|
break;
|
||||||
|
@@ -501,7 +501,7 @@ compile_load(
|
|||||||
{
|
{
|
||||||
// "var" can be script-local even without using "s:" if it
|
// "var" can be script-local even without using "s:" if it
|
||||||
// already exists in a Vim9 script or when it's imported.
|
// already exists in a Vim9 script or when it's imported.
|
||||||
if (script_var_exists(*arg, len, cctx) == OK
|
if (script_var_exists(*arg, len, cctx, NULL) == OK
|
||||||
|| find_imported(name, 0, FALSE, cctx) != NULL)
|
|| find_imported(name, 0, FALSE, cctx) != NULL)
|
||||||
res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
|
res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
|
||||||
|
|
||||||
|
@@ -600,7 +600,8 @@ handle_import(
|
|||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
else if (imported == NULL
|
else if (imported == NULL
|
||||||
&& check_defined(as_name, STRLEN(as_name), cctx, FALSE) == FAIL)
|
&& check_defined(as_name, STRLEN(as_name), cctx, NULL,
|
||||||
|
FALSE) == FAIL)
|
||||||
goto erret;
|
goto erret;
|
||||||
|
|
||||||
if (imported == NULL)
|
if (imported == NULL)
|
||||||
|
Reference in New Issue
Block a user