summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-03-23 21:36:27 +0000
committerBram Moolenaar <Bram@vim.org>2022-03-23 21:36:27 +0000
commit98b7fe725ec342d28d7c86293098b233c57c4af9 (patch)
treec67e0642a922e9d88aed6d7a7310cc057cbd48a8
parentac48506ac62b2ece523d5af6ea6c95b699d70b94 (diff)
patch 8.2.4616: Vim9: Declarations in a {} block of a user command remainv8.2.4616
Problem: Vim9: Declarations in a {} block of a user command do not use Vim9 rules if defined in a legacy script. (Yegappan Lakshmanan) Solution: Pretend the script is Vim9 script.
-rw-r--r--src/testdir/test_usercommands.vim36
-rw-r--r--src/usercmd.c20
-rw-r--r--src/version.c2
3 files changed, 58 insertions, 0 deletions
diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim
index 00bbde4906..2feeef03f9 100644
--- a/src/testdir/test_usercommands.vim
+++ b/src/testdir/test_usercommands.vim
@@ -798,4 +798,40 @@ func Test_multibyte_in_usercmd()
delcommand SubJapanesePeriodToDot
endfunc
+" Declaring a variable in a {} uses Vim9 script rules, even when defined in a
+" legacy script.
+func Test_block_declaration_legacy_script()
+ let lines =<< trim END
+ command -range Rename {
+ var save = @a
+ @a = 'something'
+ g:someExpr = @a
+ @a = save
+ }
+ END
+ call writefile(lines, 'Xlegacy')
+ source Xlegacy
+
+ let lines =<< trim END
+ let @a = 'saved'
+ Rename
+ call assert_equal('something', g:someExpr)
+ call assert_equal('saved', @a)
+
+ let g:someExpr = 'xxx'
+ let @a = 'also'
+ Rename
+ call assert_equal('something', g:someExpr)
+ call assert_equal('also', @a)
+ END
+ call writefile(lines, 'Xother')
+ source Xother
+
+ unlet g:someExpr
+ call delete('Xlegacy')
+ call delete('Xother')
+ delcommand Rename
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/usercmd.c b/src/usercmd.c
index 70dbbb03ba..40d951f6dc 100644
--- a/src/usercmd.c
+++ b/src/usercmd.c
@@ -22,6 +22,7 @@ typedef struct ucmd
int uc_compl; // completion type
cmd_addr_T uc_addr_type; // The command's address type
sctx_T uc_script_ctx; // SCTX where the command was defined
+ int uc_flags; // some UC_ flags
# ifdef FEAT_EVAL
char_u *uc_compl_arg; // completion argument if any
# endif
@@ -1038,6 +1039,7 @@ uc_add_command(
cmd->uc_script_ctx = current_sctx;
if (flags & UC_VIM9)
cmd->uc_script_ctx.sc_version = SCRIPT_VERSION_VIM9;
+ cmd->uc_flags = flags & UC_VIM9;
#ifdef FEAT_EVAL
cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM;
cmd->uc_compl_arg = compl_arg;
@@ -1725,6 +1727,9 @@ do_ucmd(exarg_T *eap)
ucmd_T *cmd;
sctx_T save_current_sctx;
int restore_current_sctx = FALSE;
+#ifdef FEAT_EVAL
+ int restore_script_version = 0;
+#endif
if (eap->cmdidx == CMD_USER)
cmd = USER_CMD(eap->useridx);
@@ -1830,6 +1835,14 @@ do_ucmd(exarg_T *eap)
current_sctx.sc_version = cmd->uc_script_ctx.sc_version;
#ifdef FEAT_EVAL
current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
+ if (cmd->uc_flags & UC_VIM9)
+ {
+ // In a {} block variables use Vim9 script rules, even in a legacy
+ // script.
+ restore_script_version =
+ SCRIPT_ITEM(current_sctx.sc_sid)->sn_version;
+ SCRIPT_ITEM(current_sctx.sc_sid)->sn_version = SCRIPT_VERSION_VIM9;
+ }
#endif
}
@@ -1839,7 +1852,14 @@ do_ucmd(exarg_T *eap)
// Careful: Do not use "cmd" here, it may have become invalid if a user
// command was added.
if (restore_current_sctx)
+ {
+#ifdef FEAT_EVAL
+ if (restore_script_version != 0)
+ SCRIPT_ITEM(current_sctx.sc_sid)->sn_version =
+ restore_script_version;
+#endif
current_sctx = save_current_sctx;
+ }
vim_free(buf);
vim_free(split_buf);
}
diff --git a/src/version.c b/src/version.c
index dd2330e4a7..ba16773e1d 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 */
/**/
+ 4616,
+/**/
4615,
/**/
4614,