changeset 25622:15b54e0a576b v8.2.3347

patch 8.2.3347: check for legacy script is incomplete Commit: https://github.com/vim/vim/commit/dd9de50f4262898384be6ea7694d05507c7cb260 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Aug 15 13:49:42 2021 +0200 patch 8.2.3347: check for legacy script is incomplete Problem: Check for legacy script is incomplete. (Naohiro Ono) Solution: Also check the :legacy modifier. Use for string concatenation with "." and others (issue #8756)
author Bram Moolenaar <Bram@vim.org>
date Sun, 15 Aug 2021 14:00:04 +0200
parents 9860aad58985
children 6d259614c0f4
files src/errors.h src/eval.c src/evalvars.c src/ex_docmd.c src/proto/vim9script.pro src/testdir/test_vim9_cmd.vim src/typval.c src/version.c src/vim9script.c
diffstat 9 files changed, 77 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/errors.h
+++ b/src/errors.h
@@ -650,3 +650,5 @@ EXTERN char e_argument_of_exists_compile
 	INIT(= N_("E1232: Argument of exists_compiled() must be a literal string"));
 EXTERN char e_exists_compiled_can_only_be_used_in_def_function[]
 	INIT(= N_("E1233: exists_compiled() can only be used in a :def function"));
+EXTERN char e_legacy_must_be_followed_by_command[]
+	INIT(= N_("E1234: legacy must be followed by a command"));
--- a/src/eval.c
+++ b/src/eval.c
@@ -2860,8 +2860,7 @@ eval5(char_u **arg, typval_T *rettv, eva
 	// "++" and "--" on the next line are a separate command.
 	p = eval_next_non_blank(*arg, evalarg, &getnext);
 	op = *p;
-	concat = op == '.' && (*(p + 1) == '.'
-			      || (current_sctx.sc_version < 2 && !vim9script));
+	concat = op == '.' && (*(p + 1) == '.' || in_old_script(2));
 	if ((op != '+' && op != '-' && !concat) || p[1] == '='
 					       || (p[1] == '.' && p[2] == '='))
 	    break;
@@ -3402,7 +3401,7 @@ eval7(
 
     if (**arg == '.' && (!isdigit(*(*arg + 1))
 #ifdef FEAT_FLOAT
-	    || current_sctx.sc_version < 2
+	    || in_old_script(2)
 #endif
 	    ))
     {
@@ -5877,7 +5876,7 @@ handle_subscript(
 		|| (**arg == '.' && (rettv->v_type == VAR_DICT
 			|| (!evaluate
 			    && (*arg)[1] != '.'
-			    && current_sctx.sc_version >= 2))))
+			    && !in_old_script(2)))))
 	{
 	    dict_unref(selfdict);
 	    if (rettv->v_type == VAR_DICT)
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -774,7 +774,7 @@ ex_let(exarg_T *eap)
 	--argend;
     expr = skipwhite(argend);
     concat = expr[0] == '.'
-	&& ((expr[1] == '=' && current_sctx.sc_version < 2)
+	&& ((expr[1] == '=' && in_old_script(2))
 		|| (expr[1] == '.' && expr[2] == '='));
     has_assign =  *expr == '=' || (vim_strchr((char_u *)"+-*/%", *expr) != NULL
 							    && expr[1] == '=');
@@ -2932,7 +2932,7 @@ find_var_ht(char_u *name, char_u **varna
 
 	// "version" is "v:version" in all scopes if scriptversion < 3.
 	// Same for a few other variables marked with VV_COMPAT.
-	if (current_sctx.sc_version < 3)
+	if (in_old_script(3))
 	{
 	    hi = hash_find(&compat_hashtab, name);
 	    if (!HASHITEM_EMPTY(hi))
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2951,7 +2951,7 @@ parse_command_modifiers(
 			    if (ends_excmd2(p, eap->cmd))
 			    {
 				*errormsg =
-				      _(e_vim9cmd_must_be_followed_by_command);
+				      _(e_legacy_must_be_followed_by_command);
 				return FAIL;
 			    }
 			    cmod->cmod_flags |= CMOD_LEGACY;
--- a/src/proto/vim9script.pro
+++ b/src/proto/vim9script.pro
@@ -1,5 +1,6 @@
 /* vim9script.c */
 int in_vim9script(void);
+int in_old_script(int max_version);
 int current_script_is_vim9(void);
 void ex_vim9script(exarg_T *eap);
 int not_in_vim9(exarg_T *eap);
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -13,10 +13,26 @@ def Test_vim9cmd()
     vim9cm assert_equal('yes', y)
   END
   CheckScriptSuccess(lines)
+
   assert_fails('vim9cmd', 'E1164:')
+  assert_fails('legacy', 'E1234:')
   assert_fails('vim9cmd echo "con" . "cat"', 'E15:')
 
   lines =<< trim END
+      let str = 'con'
+      vim9cmd str .= 'cat'
+  END
+  CheckScriptFailure(lines, 'E492:')
+
+  lines =<< trim END
+      vim9script
+      legacy echo "con" . "cat"
+      legacy let str = 'con'
+      legacy let str .= 'cat'
+  END
+  CheckScriptSuccess(lines)
+
+  lines =<< trim END
       vim9script
       def Foo()
         g:found_bar = "bar"
@@ -24,11 +40,47 @@ def Test_vim9cmd()
       nmap ,; :vim9cmd <SID>Foo()<CR>
   END
   CheckScriptSuccess(lines)
+
   feedkeys(',;', 'xt')
   assert_equal("bar", g:found_bar)
-
   nunmap ,;
   unlet g:found_bar
+
+  lines =<< trim END
+      vim9script
+      legacy echo 1'000
+  END
+  CheckScriptFailure(lines, 'E115:')
+
+  if has('float')
+    lines =<< trim END
+        vim9script
+        echo .10
+    END
+    CheckScriptSuccess(lines)
+    lines =<< trim END
+        vim9cmd echo .10
+    END
+    CheckScriptSuccess(lines)
+    lines =<< trim END
+        vim9script
+        legacy echo .10
+    END
+    CheckScriptFailure(lines, 'E15:')
+  endif
+
+  echo v:version
+  assert_fails('vim9cmd echo version', 'E121:')
+  lines =<< trim END
+      vim9script
+      echo version
+  END
+  CheckScriptFailure(lines, 'E121:')
+  lines =<< trim END
+      vim9script
+      legacy echo version
+  END
+  CheckScriptSuccess(lines)
 enddef
 
 def Test_edit_wildcards()
--- a/src/typval.c
+++ b/src/typval.c
@@ -1704,7 +1704,7 @@ eval_number(
 	int	    want_string UNUSED)
 {
     int		len;
-    int		skip_quotes = current_sctx.sc_version >= 4 || in_vim9script();
+    int		skip_quotes = !in_old_script(4);
 #ifdef FEAT_FLOAT
     char_u	*p;
     int		get_float = FALSE;
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3347,
+/**/
     3346,
 /**/
     3345,
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -34,6 +34,18 @@ in_vim9script(void)
 
 #if defined(FEAT_EVAL) || defined(PROTO)
 /*
+ * Return TRUE when currently in a script with script version smaller than
+ * "max_version" or command modifiers forced it.
+ */
+    int
+in_old_script(int max_version)
+{
+    return (current_sctx.sc_version <= max_version
+					 && !(cmdmod.cmod_flags & CMOD_VIM9CMD))
+		|| (cmdmod.cmod_flags & CMOD_LEGACY);
+}
+
+/*
  * Return TRUE if the current script is Vim9 script.
  * This also returns TRUE in a legacy function in a Vim9 script.
  */