Skip to content

Commit b2cb6c8

Browse files
committed
patch 8.2.2672: Vim9: cannot use :lockvar and :unlockvar in compiled script
Problem: Vim9: cannot use :lockvar and :unlockvar in compiled script. Solution: Implement locking support.
1 parent f6bdd82 commit b2cb6c8

File tree

4 files changed

+97
-10
lines changed

4 files changed

+97
-10
lines changed

src/errors.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,5 @@ EXTERN char e_misplaced_command_modifier[]
391391
INIT(= N_("E1176: Misplaced command modifier"));
392392
EXTERN char e_for_loop_on_str_not_supported[]
393393
INIT(= N_("E1177: For loop on %s not supported"));
394+
EXTERN char e_cannot_lock_unlock_local_variable[]
395+
INIT(= N_("E1178: Cannot lock or unlock a local variable"));

src/testdir/test_vim9_cmd.vim

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,4 +1135,42 @@ def Test_windo_missing_endif()
11351135
CheckDefExecFailure(lines, 'E171:', 1)
11361136
enddef
11371137

1138+
let s:theList = [1, 2, 3]
1139+
1140+
def Test_lockvar()
1141+
s:theList[1] = 22
1142+
assert_equal([1, 22, 3], s:theList)
1143+
lockvar s:theList
1144+
assert_fails('theList[1] = 77', 'E741:')
1145+
unlockvar s:theList
1146+
s:theList[1] = 44
1147+
assert_equal([1, 44, 3], s:theList)
1148+
1149+
var lines =<< trim END
1150+
vim9script
1151+
var theList = [1, 2, 3]
1152+
def SetList()
1153+
theList[1] = 22
1154+
assert_equal([1, 22, 3], theList)
1155+
lockvar theList
1156+
theList[1] = 77
1157+
enddef
1158+
SetList()
1159+
END
1160+
CheckScriptFailure(lines, 'E1119', 4)
1161+
1162+
lines =<< trim END
1163+
var theList = [1, 2, 3]
1164+
lockvar theList
1165+
END
1166+
CheckDefFailure(lines, 'E1178', 2)
1167+
1168+
lines =<< trim END
1169+
var theList = [1, 2, 3]
1170+
unlockvar theList
1171+
END
1172+
CheckDefFailure(lines, 'E1178', 2)
1173+
enddef
1174+
1175+
11381176
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2672,
753755
/**/
754756
2671,
755757
/**/

src/vim9compile.c

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6708,22 +6708,67 @@ compile_unlet(
67086708
}
67096709

67106710
/*
6711-
* compile "unlet var", "lock var" and "unlock var"
6712-
* "arg" points to "var".
6711+
* Callback passed to ex_unletlock().
67136712
*/
6714-
static char_u *
6715-
compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
6713+
static int
6714+
compile_lock_unlock(
6715+
lval_T *lvp,
6716+
char_u *name_end,
6717+
exarg_T *eap,
6718+
int deep UNUSED,
6719+
void *coookie)
67166720
{
6717-
char_u *p = arg;
6721+
cctx_T *cctx = coookie;
6722+
int cc = *name_end;
6723+
char_u *p = lvp->ll_name;
6724+
int ret = OK;
6725+
size_t len;
6726+
char_u *buf;
67186727

6719-
if (eap->cmdidx != CMD_unlet)
6728+
if (cctx->ctx_skip == SKIP_YES)
6729+
return OK;
6730+
6731+
// Cannot use :lockvar and :unlockvar on local variables.
6732+
if (p[1] != ':')
67206733
{
6721-
emsg("Sorry, :lock and unlock not implemented yet");
6722-
return NULL;
6734+
char_u *end = skip_var_one(p, FALSE);
6735+
6736+
if (lookup_local(p, end - p, NULL, cctx) == OK)
6737+
{
6738+
emsg(_(e_cannot_lock_unlock_local_variable));
6739+
return FAIL;
6740+
}
67236741
}
67246742

6725-
ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
6726-
compile_unlet, cctx);
6743+
// Checking is done at runtime.
6744+
*name_end = NUL;
6745+
len = name_end - p + 20;
6746+
buf = alloc(len);
6747+
if (buf == NULL)
6748+
ret = FAIL;
6749+
else
6750+
{
6751+
vim_snprintf((char *)buf, len, "%s %s",
6752+
eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
6753+
p);
6754+
ret = generate_EXEC(cctx, buf);
6755+
6756+
vim_free(buf);
6757+
*name_end = cc;
6758+
}
6759+
return ret;
6760+
}
6761+
6762+
/*
6763+
* compile "unlet var", "lock var" and "unlock var"
6764+
* "arg" points to "var".
6765+
*/
6766+
static char_u *
6767+
compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
6768+
{
6769+
ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
6770+
eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
6771+
cctx);
67276772
return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
67286773
}
67296774

0 commit comments

Comments
 (0)