From b2cb6c8bbd215177ed05c1d952e7ef2ad8f7ef4b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 28 Mar 2021 20:38:34 +0200 Subject: [PATCH] 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. --- src/errors.h | 2 ++ src/testdir/test_vim9_cmd.vim | 38 ++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 65 +++++++++++++++++++++++++++++------ 4 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/errors.h b/src/errors.h index cb0f84652..e43cddb85 100644 --- a/src/errors.h +++ b/src/errors.h @@ -391,3 +391,5 @@ EXTERN char e_misplaced_command_modifier[] INIT(= N_("E1176: Misplaced command modifier")); EXTERN char e_for_loop_on_str_not_supported[] INIT(= N_("E1177: For loop on %s not supported")); +EXTERN char e_cannot_lock_unlock_local_variable[] + INIT(= N_("E1178: Cannot lock or unlock a local variable")); diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index bc4cfa6e1..3b479f31d 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -1135,4 +1135,42 @@ def Test_windo_missing_endif() CheckDefExecFailure(lines, 'E171:', 1) enddef +let s:theList = [1, 2, 3] + +def Test_lockvar() + s:theList[1] = 22 + assert_equal([1, 22, 3], s:theList) + lockvar s:theList + assert_fails('theList[1] = 77', 'E741:') + unlockvar s:theList + s:theList[1] = 44 + assert_equal([1, 44, 3], s:theList) + + var lines =<< trim END + vim9script + var theList = [1, 2, 3] + def SetList() + theList[1] = 22 + assert_equal([1, 22, 3], theList) + lockvar theList + theList[1] = 77 + enddef + SetList() + END + CheckScriptFailure(lines, 'E1119', 4) + + lines =<< trim END + var theList = [1, 2, 3] + lockvar theList + END + CheckDefFailure(lines, 'E1178', 2) + + lines =<< trim END + var theList = [1, 2, 3] + unlockvar theList + END + CheckDefFailure(lines, 'E1178', 2) +enddef + + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 1937de121..602fdb622 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2672, /**/ 2671, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index c1adb36c6..26d346f43 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6708,22 +6708,67 @@ compile_unlet( } /* - * compile "unlet var", "lock var" and "unlock var" - * "arg" points to "var". + * Callback passed to ex_unletlock(). */ - static char_u * -compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx) + static int +compile_lock_unlock( + lval_T *lvp, + char_u *name_end, + exarg_T *eap, + int deep UNUSED, + void *coookie) { - char_u *p = arg; + cctx_T *cctx = coookie; + int cc = *name_end; + char_u *p = lvp->ll_name; + int ret = OK; + size_t len; + char_u *buf; - if (eap->cmdidx != CMD_unlet) + if (cctx->ctx_skip == SKIP_YES) + return OK; + + // Cannot use :lockvar and :unlockvar on local variables. + if (p[1] != ':') { - emsg("Sorry, :lock and unlock not implemented yet"); - return NULL; + char_u *end = skip_var_one(p, FALSE); + + if (lookup_local(p, end - p, NULL, cctx) == OK) + { + emsg(_(e_cannot_lock_unlock_local_variable)); + return FAIL; + } } - ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD | GLV_COMPILING, - compile_unlet, cctx); + // Checking is done at runtime. + *name_end = NUL; + len = name_end - p + 20; + buf = alloc(len); + if (buf == NULL) + ret = FAIL; + else + { + vim_snprintf((char *)buf, len, "%s %s", + eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar", + p); + ret = generate_EXEC(cctx, buf); + + vim_free(buf); + *name_end = cc; + } + return ret; +} + +/* + * compile "unlet var", "lock var" and "unlock var" + * "arg" points to "var". + */ + static char_u * +compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx) +{ + ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING, + eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock, + cctx); return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd; } -- 2.40.0