]> granicus.if.org Git - vim/commitdiff
patch 8.1.1722: error when scriptversion is 2 a making a dictionary access v8.1.1722
authorBram Moolenaar <Bram@vim.org>
Sat, 20 Jul 2019 19:11:13 +0000 (21:11 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 20 Jul 2019 19:11:13 +0000 (21:11 +0200)
Problem:    Error when scriptversion is 2 a making a dictionary access.
Solution:   Parse the subscript even when not evaluating the sub-expression.
            (closes #4704)

src/eval.c
src/testdir/test_eval_stuff.vim
src/version.c

index 8e9d01308e57d67d5bfd90fa11fa842dc3591bd0..d633f4502e8eb4158c354e126d826ad085700187 100644 (file)
@@ -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)))
index 08ab59ea53d7d23d245eee9b63dabbf9b7eeb4a9..82f9cac243e61da4b3b158a56b91a260a99038f8 100644 (file)
@@ -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:')
index 4d270650c675c5aaacdf667b1adebffaecfbdeda..36a7779471da072ff02491e35cfd26e317399914 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1722,
 /**/
     1721,
 /**/