summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-04-04 14:58:06 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-04 14:58:06 +0100
commit7a411a306f90339d8686e42ac16e1ae4fc7533c5 (patch)
treedef2607a7145867c305c4d55baf955bc21649bde
parent15f74fab653a784548d5d966644926b47ba2cfa7 (diff)
downloadvim-git-7a411a306f90339d8686e42ac16e1ae4fc7533c5.tar.gz
patch 8.2.4682: Vim9: can use :unlockvar for const variablev8.2.4682
Problem: Vim9: can use :unlockvar for const variable. (Ernie Rael) Solution: Check whether the variable is a const.
-rw-r--r--src/eval.c2
-rw-r--r--src/evalvars.c51
-rw-r--r--src/ex_docmd.c1
-rw-r--r--src/proto/vim9script.pro2
-rw-r--r--src/testdir/test_vim9_cmd.vim17
-rw-r--r--src/userfunc.c2
-rw-r--r--src/version.c2
-rw-r--r--src/vim9script.c8
8 files changed, 62 insertions, 23 deletions
diff --git a/src/eval.c b/src/eval.c
index 2cde64216..b30577fec 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1065,7 +1065,7 @@ get_lval(
&& lp->ll_tv == &v->di_tv
&& 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
if (sv != NULL)
diff --git a/src/evalvars.c b/src/evalvars.c
index dd70427d3..c1ec5b0ba 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1951,23 +1951,42 @@ do_lock_var(
lp->ll_name);
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
{
- if (lock)
- di->di_flags |= DI_FLAGS_LOCK;
+ 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
- di->di_flags &= ~DI_FLAGS_LOCK;
- if (deep != 0)
- item_lock(&di->di_tv, deep, lock, FALSE);
+ {
+ if (in_vim9script())
+ {
+ 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;
@@ -2812,7 +2831,7 @@ eval_variable(
if (ht != NULL && ht == get_script_local_ht()
&& 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)
type = sv->sv_type;
@@ -3557,7 +3576,7 @@ set_var_const(
if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
{
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)
{
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index c12f151c3..2d5752445 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -303,7 +303,6 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name);
# define ex_throw ex_ni
# define ex_try ex_ni
# define ex_unlet ex_ni
-# define ex_unlockvar ex_ni
# define ex_while ex_ni
# define ex_import ex_ni
# define ex_export ex_ni
diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro
index bc1e23275..04c07fc32 100644
--- a/src/proto/vim9script.pro
+++ b/src/proto/vim9script.pro
@@ -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);
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);
-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_reserved_name(char_u *name);
/* vim: set ft=c : */
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 8dea71d5f..49ca29b67 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -1650,6 +1650,23 @@ def Test_lockvar()
LockIt()
END
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
def Test_substitute_expr()
diff --git a/src/userfunc.c b/src/userfunc.c
index 052923e94..c80a49051 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1697,7 +1697,7 @@ deref_func_name(
{
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)
*type = sv->sv_type;
diff --git a/src/version.c b/src/version.c
index 79a3bad67..8b7450c66 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4682,
+/**/
4681,
/**/
4680,
diff --git a/src/vim9script.c b/src/vim9script.c
index cd9ff92cd..adb01e8b9 100644
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -956,7 +956,7 @@ update_vim9_script_var(
}
else
{
- sv = find_typval_in_script(&di->di_tv, 0);
+ sv = find_typval_in_script(&di->di_tv, 0, TRUE);
}
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".
* 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.
*/
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);
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)
return sv;
}
- iemsg("find_typval_in_script(): not found");
+ if (must_find)
+ iemsg("find_typval_in_script(): not found");
return NULL;
}