changeset 21630:3c6c52fbc8ea v8.2.1365

patch 8.2.1365: Vim9: no error for missing white space around operator Commit: https://github.com/vim/vim/commit/bb1b5e24ecc0abe1fee164e9de13796989eff784 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Aug 5 10:53:21 2020 +0200 patch 8.2.1365: Vim9: no error for missing white space around operator Problem: Vim9: no error for missing white space around operator. Solution: Check for white space. (closes https://github.com/vim/vim/issues/6618)
author Bram Moolenaar <Bram@vim.org>
date Wed, 05 Aug 2020 11:00:08 +0200
parents 87a1c4717817
children e55aba8c2146
files src/eval.c src/evalvars.c src/proto/vim9compile.pro src/testdir/test_vim9_expr.vim src/testdir/test_vim9_func.vim src/version.c src/vim9compile.c
diffstat 7 files changed, 80 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -2574,6 +2574,7 @@ eval5(char_u **arg, typval_T *rettv, eva
 	int	    getnext;
 	char_u	    *p;
 	int	    op;
+	int	    oplen;
 	int	    concat;
 	typval_T    var2;
 
@@ -2584,11 +2585,19 @@ eval5(char_u **arg, typval_T *rettv, eva
 	if (op != '+' && op != '-' && !concat)
 	    break;
 
+	evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
 	if (getnext)
 	    *arg = eval_next_line(evalarg);
 	else
+	{
+	    if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg))
+	    {
+		error_white_both(p, 1);
+		clear_tv(rettv);
+		return FAIL;
+	    }
 	    *arg = p;
-	evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
+	}
 	if ((op != '+' || (rettv->v_type != VAR_LIST
 						 && rettv->v_type != VAR_BLOB))
 #ifdef FEAT_FLOAT
@@ -2613,9 +2622,14 @@ eval5(char_u **arg, typval_T *rettv, eva
 	/*
 	 * Get the second variable.
 	 */
-	if (op == '.' && *(*arg + 1) == '.')  // .. string concatenation
-	    ++*arg;
-	*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
+	oplen = (op == '.' && *(*arg + 1) == '.') ? 2 : 1;
+	if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[oplen]))
+	{
+	    error_white_both(p, oplen);
+	    clear_tv(rettv);
+	    return FAIL;
+	}
+	*arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
 	if (eval6(arg, &var2, evalarg, op == '.') == FAIL)
 	{
 	    clear_tv(rettv);
@@ -3358,6 +3372,7 @@ eval_method(
     }
     else
     {
+	*arg = skipwhite(*arg);
 	if (**arg != '(')
 	{
 	    if (verbose)
@@ -4841,7 +4856,7 @@ get_env_len(char_u **arg)
 
 /*
  * Get the length of the name of a function or internal variable.
- * "arg" is advanced to the first non-white character after the name.
+ * "arg" is advanced to after the name.
  * Return 0 if something is wrong.
  */
     int
@@ -4867,7 +4882,7 @@ get_id_len(char_u **arg)
 	return 0;
 
     len = (int)(p - *arg);
-    *arg = skipwhite(p);
+    *arg = p;
 
     return len;
 }
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1137,6 +1137,7 @@ list_arg_vars(exarg_T *eap, char_u *arg,
 	    }
 	    else
 	    {
+		arg = skipwhite(arg);
 		if (tofree != NULL)
 		    name = tofree;
 		if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
@@ -3358,6 +3359,7 @@ assert_error(garray_T *gap)
     int
 var_exists(char_u *var)
 {
+    char_u	*arg = var;
     char_u	*name;
     char_u	*tofree;
     typval_T    tv;
@@ -3366,7 +3368,7 @@ var_exists(char_u *var)
 
     // get_name_len() takes care of expanding curly braces
     name = var;
-    len = get_name_len(&var, &tofree, TRUE, FALSE);
+    len = get_name_len(&arg, &tofree, TRUE, FALSE);
     if (len > 0)
     {
 	if (tofree != NULL)
@@ -3375,12 +3377,13 @@ var_exists(char_u *var)
 	if (n)
 	{
 	    // handle d.key, l[idx], f(expr)
-	    n = (handle_subscript(&var, &tv, &EVALARG_EVALUATE, FALSE) == OK);
+	    arg = skipwhite(arg);
+	    n = (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, FALSE) == OK);
 	    if (n)
 		clear_tv(&tv);
 	}
     }
-    if (*var != NUL)
+    if (*arg != NUL)
 	n = FALSE;
 
     vim_free(tofree);
--- a/src/proto/vim9compile.pro
+++ b/src/proto/vim9compile.pro
@@ -17,6 +17,7 @@ char_u *peek_next_line_from_context(cctx
 char_u *next_line_from_context(cctx_T *cctx, int skip_comment);
 char_u *to_name_const_end(char_u *arg);
 exptype_T get_compare_type(char_u *p, int *len, int *type_is);
+void error_white_both(char_u *op, int len);
 int assignment_len(char_u *p, int *heredoc);
 void vim9_declare_error(char_u *name);
 int check_vim9_unlet(char_u *name);
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -872,6 +872,39 @@ def Test_expr5_vim9script()
       echo 'abc' isnot? 'abc'
   END
   CheckScriptFailure(lines, 'E15:')
+
+  # check white space
+  lines =<< trim END
+      vim9script
+      echo 5+6
+  END
+  CheckScriptFailure(lines, 'E1004:')
+  lines =<< trim END
+      vim9script
+      echo 5 +6
+  END
+  CheckScriptFailure(lines, 'E1004:')
+  lines =<< trim END
+      vim9script
+      echo 5+ 6
+  END
+  CheckScriptFailure(lines, 'E1004:')
+
+  lines =<< trim END
+      vim9script
+      echo 'a'..'b'
+  END
+  CheckScriptFailure(lines, 'E1004:')
+  lines =<< trim END
+      vim9script
+      echo 'a' ..'b'
+  END
+  CheckScriptFailure(lines, 'E1004:')
+  lines =<< trim END
+      vim9script
+      echo 'a'.. 'b'
+  END
+  CheckScriptFailure(lines, 'E1004:')
 enddef
 
 def Test_expr5_float()
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -1270,7 +1270,7 @@ enddef
 def TreeWalk(dir: string): list<any>
   return readdir(dir)->map({_, val ->
             fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
-               ? {val : TreeWalk(dir .. '/' .. val)}
+               ? {val: TreeWalk(dir .. '/' .. val)}
                : val
              })
 enddef
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1365,
+/**/
     1364,
 /**/
     1363,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -4244,6 +4244,18 @@ compile_expr7(
 }
 
 /*
+ * Give the "white on both sides" error, taking the operator from "p[len]".
+ */
+    void
+error_white_both(char_u *op, int len)
+{
+    char_u	buf[10];
+
+    vim_strncpy(buf, op, len);
+    semsg(_(e_white_both), buf);
+}
+
+/*
  *	*	number multiplication
  *	/	number division
  *	%	number modulo
@@ -4275,10 +4287,7 @@ compile_expr6(char_u **arg, cctx_T *cctx
 
 	if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
 	{
-	    char_u buf[3];
-
-	    vim_strncpy(buf, op, 1);
-	    semsg(_(e_white_both), buf);
+	    error_white_both(op, 1);
 	    return FAIL;
 	}
 	*arg = skipwhite(op + 1);
@@ -4354,10 +4363,7 @@ compile_expr5(char_u **arg, cctx_T *cctx
 
 	if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
 	{
-	    char_u buf[3];
-
-	    vim_strncpy(buf, op, oplen);
-	    semsg(_(e_white_both), buf);
+	    error_white_both(op, oplen);
 	    return FAIL;
 	}
 
@@ -4486,10 +4492,7 @@ compile_expr4(char_u **arg, cctx_T *cctx
 
 	if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
 	{
-	    char_u buf[7];
-
-	    vim_strncpy(buf, p, len);
-	    semsg(_(e_white_both), buf);
+	    error_white_both(p, len);
 	    return FAIL;
 	}
 
@@ -5132,10 +5135,7 @@ compile_assignment(char_u *arg, exarg_T 
 
     if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
     {
-	char_u  buf[4];
-
-	vim_strncpy(buf, op, oplen);
-	semsg(_(e_white_both), buf);
+	error_white_both(op, oplen);
 	return NULL;
     }