changeset 17448:f8cd16838434 v8.1.1722

patch 8.1.1722: error when scriptversion is 2 a making a dictionary access commit https://github.com/vim/vim/commit/61343f0c44c8e71df04918d033e0a744c0b7f8aa Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jul 20 21:11:13 2019 +0200 patch 8.1.1722: error when scriptversion is 2 a making a dictionary access Problem: Error when scriptversion is 2 a making a dictionary access. Solution: Parse the subscript even when not evaluating the sub-expression. (closes #4704)
author Bram Moolenaar <Bram@vim.org>
date Sat, 20 Jul 2019 21:15:04 +0200
parents c8bdaff91140
children 3f12449a6020
files src/eval.c src/testdir/test_eval_stuff.vim src/version.c
diffstat 3 files changed, 20 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -1486,7 +1486,7 @@ ex_let_const(exarg_T *eap, int is_const)
 /*
  * Assign the typevalue "tv" to the variable or variables at "arg_start".
  * Handles both "var" with any type and "[var, var; var]" with a list type.
- * When "nextchars" is not NULL it points to a string with characters that
+ * When "op" is not NULL it points to a string with characters that
  * must appear after the variable(s).  Use "+", "-" or "." for add, subtract
  * or concatenate.
  * Returns OK or FAIL;
@@ -1499,7 +1499,7 @@ ex_let_vars(
     int		semicolon,	// from skip_var_list()
     int		var_count,	// from skip_var_list()
     int		is_const,	// lock variables for const
-    char_u	*nextchars)
+    char_u	*op)
 {
     char_u	*arg = arg_start;
     list_T	*l;
@@ -1512,7 +1512,7 @@ ex_let_vars(
 	/*
 	 * ":let var = expr" or ":for var in list"
 	 */
-	if (ex_let_one(arg, tv, copy, is_const, nextchars, nextchars) == NULL)
+	if (ex_let_one(arg, tv, copy, is_const, op, op) == NULL)
 	    return FAIL;
 	return OK;
     }
@@ -1543,7 +1543,7 @@ ex_let_vars(
     {
 	arg = skipwhite(arg + 1);
 	arg = ex_let_one(arg, &item->li_tv, TRUE, is_const,
-						   (char_u *)",;]", nextchars);
+							  (char_u *)",;]", op);
 	item = item->li_next;
 	if (arg == NULL)
 	    return FAIL;
@@ -1568,7 +1568,7 @@ ex_let_vars(
 	    l->lv_refcount = 1;
 
 	    arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, is_const,
-						     (char_u *)"]", nextchars);
+							    (char_u *)"]", op);
 	    clear_tv(&ltv);
 	    if (arg == NULL)
 		return FAIL;
@@ -7355,9 +7355,14 @@ handle_subscript(
     int		len;
     typval_T	functv;
 
+    // "." is ".name" lookup when we found a dict or when evaluating and
+    // scriptversion is at least 2, where string concatenation is "..".
     while (ret == OK
 	    && (**arg == '['
-		|| (**arg == '.' && rettv->v_type == VAR_DICT)
+		|| (**arg == '.' && (rettv->v_type == VAR_DICT
+			|| (!evaluate
+			    && (*arg)[1] != '.'
+			    && current_sctx.sc_version >= 2)))
 		|| (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
 					    || rettv->v_type == VAR_PARTIAL)))
 	    && !VIM_ISWHITE(*(*arg - 1)))
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -176,6 +176,13 @@ func Test_vvar_scriptversion2()
   call assert_true(v:versionlong > 8011525)
 endfunc
 
+func Test_dict_access_scriptversion2()
+  let l:x = {'foo': 1}
+
+  call assert_false(0 && l:x.foo)
+  call assert_true(1 && l:x.foo)
+endfunc
+
 func Test_scriptversion()
   call writefile(['scriptversion 9'], 'Xversionscript')
   call assert_fails('source Xversionscript', 'E999:')
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1722,
+/**/
     1721,
 /**/
     1720,