changeset 28181:2961a18f9cbf v8.2.4616

patch 8.2.4616: Vim9: Declarations in a {} block of a user command remain Commit: https://github.com/vim/vim/commit/98b7fe725ec342d28d7c86293098b233c57c4af9 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Mar 23 21:36:27 2022 +0000 patch 8.2.4616: Vim9: Declarations in a {} block of a user command remain 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.
author Bram Moolenaar <Bram@vim.org>
date Wed, 23 Mar 2022 22:45:06 +0100
parents d56d48f416b1
children 2846627df454
files src/testdir/test_usercommands.vim src/usercmd.c src/version.c
diffstat 3 files changed, 58 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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);
 }
--- 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,