0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

patch 8.2.4682: Vim9: can use :unlockvar for const variable

Problem:    Vim9: can use :unlockvar for const variable. (Ernie Rael)
Solution:   Check whether the variable is a const.
This commit is contained in:
Bram Moolenaar
2022-04-04 14:58:06 +01:00
parent 15f74fab65
commit 7a411a306f
8 changed files with 62 additions and 23 deletions

View File

@@ -1065,7 +1065,7 @@ get_lval(
&& lp->ll_tv == &v->di_tv && lp->ll_tv == &v->di_tv
&& ht != NULL && ht == get_script_local_ht()) && ht != NULL && ht == get_script_local_ht())
{ {
svar_T *sv = find_typval_in_script(lp->ll_tv, 0); svar_T *sv = find_typval_in_script(lp->ll_tv, 0, TRUE);
// Vim9 script local variable: get the type // Vim9 script local variable: get the type
if (sv != NULL) if (sv != NULL)

View File

@@ -1951,23 +1951,42 @@ do_lock_var(
lp->ll_name); lp->ll_name);
ret = FAIL; ret = FAIL;
} }
else if ((di->di_flags & DI_FLAGS_FIX)
&& di->di_tv.v_type != VAR_DICT
&& di->di_tv.v_type != VAR_LIST)
{
// For historic reasons this error is not given for a list or
// dict. E.g., the b: dict could be locked/unlocked.
semsg(_(e_cannot_lock_or_unlock_variable_str), lp->ll_name);
ret = FAIL;
}
else else
{ {
if (lock) if ((di->di_flags & DI_FLAGS_FIX)
di->di_flags |= DI_FLAGS_LOCK; && di->di_tv.v_type != VAR_DICT
&& di->di_tv.v_type != VAR_LIST)
{
// For historic reasons this error is not given for a list
// or dict. E.g., the b: dict could be locked/unlocked.
semsg(_(e_cannot_lock_or_unlock_variable_str), lp->ll_name);
ret = FAIL;
}
else else
di->di_flags &= ~DI_FLAGS_LOCK; {
if (deep != 0) if (in_vim9script())
item_lock(&di->di_tv, deep, lock, FALSE); {
svar_T *sv = find_typval_in_script(&di->di_tv,
0, FALSE);
if (sv != NULL && sv->sv_const != 0)
{
semsg(_(e_cannot_change_readonly_variable_str),
lp->ll_name);
ret = FAIL;
}
}
if (ret == OK)
{
if (lock)
di->di_flags |= DI_FLAGS_LOCK;
else
di->di_flags &= ~DI_FLAGS_LOCK;
if (deep != 0)
item_lock(&di->di_tv, deep, lock, FALSE);
}
}
} }
} }
*name_end = cc; *name_end = cc;
@@ -2812,7 +2831,7 @@ eval_variable(
if (ht != NULL && ht == get_script_local_ht() if (ht != NULL && ht == get_script_local_ht()
&& tv != &SCRIPT_SV(current_sctx.sc_sid)->sv_var.di_tv) && tv != &SCRIPT_SV(current_sctx.sc_sid)->sv_var.di_tv)
{ {
svar_T *sv = find_typval_in_script(tv, 0); svar_T *sv = find_typval_in_script(tv, 0, TRUE);
if (sv != NULL) if (sv != NULL)
type = sv->sv_type; type = sv->sv_type;
@@ -3557,7 +3576,7 @@ set_var_const(
if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0) if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
{ {
where_T where = WHERE_INIT; where_T where = WHERE_INIT;
svar_T *sv = find_typval_in_script(&di->di_tv, sid); svar_T *sv = find_typval_in_script(&di->di_tv, sid, TRUE);
if (sv != NULL) if (sv != NULL)
{ {

View File

@@ -303,7 +303,6 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name);
# define ex_throw ex_ni # define ex_throw ex_ni
# define ex_try ex_ni # define ex_try ex_ni
# define ex_unlet ex_ni # define ex_unlet ex_ni
# define ex_unlockvar ex_ni
# define ex_while ex_ni # define ex_while ex_ni
# define ex_import ex_ni # define ex_import ex_ni
# define ex_export ex_ni # define ex_export ex_ni

View File

@@ -16,7 +16,7 @@ int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg); char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
void update_vim9_script_var(int create, dictitem_T *di, char_u *name, int flags, typval_T *tv, type_T **type, int do_member); void update_vim9_script_var(int create, dictitem_T *di, char_u *name, int flags, typval_T *tv, type_T **type, int do_member);
void hide_script_var(scriptitem_T *si, int idx, int func_defined); void hide_script_var(scriptitem_T *si, int idx, int func_defined);
svar_T *find_typval_in_script(typval_T *dest, scid_T sid); svar_T *find_typval_in_script(typval_T *dest, scid_T sid, int must_find);
int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where); int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where);
int check_reserved_name(char_u *name); int check_reserved_name(char_u *name);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@@ -1650,6 +1650,23 @@ def Test_lockvar()
LockIt() LockIt()
END END
v9.CheckScriptFailure(lines, 'E1246', 1) v9.CheckScriptFailure(lines, 'E1246', 1)
lines =<< trim END
vim9script
const name = 'john'
unlockvar name
END
v9.CheckScriptFailure(lines, 'E46', 3)
lines =<< trim END
vim9script
const name = 'john'
def UnLockIt()
unlockvar name
enddef
UnLockIt()
END
v9.CheckScriptFailure(lines, 'E46', 1)
enddef enddef
def Test_substitute_expr() def Test_substitute_expr()

View File

@@ -1697,7 +1697,7 @@ deref_func_name(
{ {
if (!did_type && type != NULL && ht == get_script_local_ht()) if (!did_type && type != NULL && ht == get_script_local_ht())
{ {
svar_T *sv = find_typval_in_script(tv, 0); svar_T *sv = find_typval_in_script(tv, 0, TRUE);
if (sv != NULL) if (sv != NULL)
*type = sv->sv_type; *type = sv->sv_type;

View File

@@ -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 */
/**/
4682,
/**/ /**/
4681, 4681,
/**/ /**/

View File

@@ -956,7 +956,7 @@ update_vim9_script_var(
} }
else else
{ {
sv = find_typval_in_script(&di->di_tv, 0); sv = find_typval_in_script(&di->di_tv, 0, TRUE);
} }
if (sv != NULL) if (sv != NULL)
{ {
@@ -1053,10 +1053,11 @@ hide_script_var(scriptitem_T *si, int idx, int func_defined)
/* /*
* Find the script-local variable that links to "dest". * Find the script-local variable that links to "dest".
* If "sid" is zero use the current script. * If "sid" is zero use the current script.
* if "must_find" is TRUE and "dest" cannot be found report an internal error.
* Returns NULL if not found and give an internal error. * Returns NULL if not found and give an internal error.
*/ */
svar_T * svar_T *
find_typval_in_script(typval_T *dest, scid_T sid) find_typval_in_script(typval_T *dest, scid_T sid, int must_find)
{ {
scriptitem_T *si = SCRIPT_ITEM(sid == 0 ? current_sctx.sc_sid : sid); scriptitem_T *si = SCRIPT_ITEM(sid == 0 ? current_sctx.sc_sid : sid);
int idx; int idx;
@@ -1076,7 +1077,8 @@ find_typval_in_script(typval_T *dest, scid_T sid)
if (sv->sv_name != NULL && sv->sv_tv == dest) if (sv->sv_name != NULL && sv->sv_tv == dest)
return sv; return sv;
} }
iemsg("find_typval_in_script(): not found"); if (must_find)
iemsg("find_typval_in_script(): not found");
return NULL; return NULL;
} }