]> granicus.if.org Git - vim/commitdiff
patch 8.2.1306: checking for first character of dict key is inconsistent v8.2.1306
authorBram Moolenaar <Bram@vim.org>
Mon, 27 Jul 2020 19:43:28 +0000 (21:43 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 27 Jul 2020 19:43:28 +0000 (21:43 +0200)
Problem:    Checking for first character of dict key is inconsistent.
Solution:   Add eval_isdictc(). (closes #6546)

src/eval.c
src/proto/eval.pro
src/testdir/test_let.vim
src/testdir/test_listdict.vim
src/testdir/test_vim9_expr.vim
src/version.c
src/vim9compile.c

index 6d3d19ee83192cda9ccff654d5c962879473abef..81913c7a353012a99623531ce50b31e9e19073d9 100644 (file)
@@ -3464,7 +3464,7 @@ eval_index(
         * dict.name
         */
        key = *arg + 1;
-       for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
+       for (len = 0; eval_isdictc(key[len]); ++len)
            ;
        if (len == 0)
            return FAIL;
@@ -4997,7 +4997,7 @@ find_name_end(
                    && (eval_isnamec(*p)
                        || (*p == '{' && !vim9script)
                        || ((flags & FNE_INCL_BR) && (*p == '['
-                                       || (*p == '.' && eval_isnamec1(p[1]))))
+                                        || (*p == '.' && eval_isdictc(p[1]))))
                        || mb_nest != 0
                        || br_nest != 0); MB_PTR_ADV(p))
     {
@@ -5128,7 +5128,7 @@ make_expanded_name(
     int
 eval_isnamec(int c)
 {
-    return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
+    return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR;
 }
 
 /*
@@ -5138,7 +5138,17 @@ eval_isnamec(int c)
     int
 eval_isnamec1(int c)
 {
-    return (ASCII_ISALPHA(c) || c == '_');
+    return ASCII_ISALPHA(c) || c == '_';
+}
+
+/*
+ * Return TRUE if character "c" can be used as the first character of a
+ * dictionary key.
+ */
+    int
+eval_isdictc(int c)
+{
+    return ASCII_ISALNUM(c) || c == '_';
 }
 
 /*
@@ -5171,8 +5181,7 @@ handle_subscript(
        // the next line then consume the line break.
        p = eval_next_non_blank(*arg, evalarg, &getnext);
        if (getnext
-           && ((rettv->v_type == VAR_DICT && *p == '.'
-                                                      && ASCII_ISALPHA(p[1]))
+           && ((rettv->v_type == VAR_DICT && *p == '.' && eval_isdictc(p[1]))
                || (*p == '-' && p[1] == '>'
                                     && (p[2] == '{' || ASCII_ISALPHA(p[2])))))
        {
index 5d04e01acbf855dae64a70dab6a99e4f0f5cd41c..a528d3e4356a8920c1124e0e54556709bd42229d 100644 (file)
@@ -58,6 +58,7 @@ int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose);
 char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags);
 int eval_isnamec(int c);
 int eval_isnamec1(int c);
+int eval_isdictc(int c);
 int handle_subscript(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
 int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
 void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr);
index 9a399e8f38b64bf32190a226f2bf80123f6437f1..017b2a4a478c3375dd5ded96eacfc51e5f5c9ee0 100644 (file)
@@ -293,7 +293,7 @@ func Test_let_errors()
   let s = "var"
   let var = 1
   call assert_fails('let var += [1,2]', 'E734:')
-  call assert_fails('let {s}.1 = 2', 'E15:')
+  call assert_fails('let {s}.1 = 2', 'E18:')
   call assert_fails('let a[1] = 5', 'E121:')
   let l = [[1,2]]
   call assert_fails('let l[:][0] = [5]', 'E708:')
index b064846993ad60dc293ae86c48445441e60ef226..beeda2f5bb598b5efa2e01a80eeda6e255dccb89 100644 (file)
@@ -282,6 +282,13 @@ func Test_dict_func()
   call assert_equal('xxx3', Fn('xxx'))
 endfunc
 
+func Test_dict_assign()
+  let d = {}
+  let d.1 = 1
+  let d._ = 2
+  call assert_equal({'1': 1, '_': 2}, d)
+endfunc
+
 " Function in script-local List or Dict
 func Test_script_local_dict_func()
   let g:dict = {}
index d7072f34b9fa2631b72e8c0843460045ebfe3a2b..5b46c32f96e201ef32b8e1fd7524226d7349d23d 100644 (file)
@@ -1310,6 +1310,11 @@ def Test_expr_member()
                  ])
   assert_equal(1, d
        .one)
+  d = {'1': 1, '_': 2}
+  assert_equal(1, d
+       .1)
+  assert_equal(2, d
+       ._)
 
   # getting the one member should clear the dict after getting the item
   assert_equal('one', #{one: 'one'}.one)
@@ -1330,10 +1335,16 @@ def Test_expr_member_vim9script()
       vim9script
       let d = #{one:
                'one',
-               two: 'two'}
+               two: 'two',
+               1: 1,
+               _: 2}
       assert_equal('one', d.one)
       assert_equal('one', d
                             .one)
+      assert_equal(1, d
+                            .1)
+      assert_equal(2, d
+                            ._)
       assert_equal('one', d[
                            'one'
                            ])
index ec702330b232a0f6267bf506dc8c0a91889fa2bb..a87cc89d37ff4f66ea7c9b6880645eeaf5c4f11a 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1306,
 /**/
     1305,
 /**/
index 8efb1f672fd8e27143d9bc1b48353d0b29a430e3..1ed3211463a0975d5f1438f0005fb3730335fd18 100644 (file)
@@ -3758,7 +3758,7 @@ compile_subscript(
            if (next != NULL &&
                    ((next[0] == '-' && next[1] == '>'
                                 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
-                   || (next[0] == '.' && ASCII_ISALPHA(next[1]))))
+                   || (next[0] == '.' && eval_isdictc(next[1]))))
            {
                next = next_line_from_context(cctx, TRUE);
                if (next == NULL)
@@ -3922,7 +3922,7 @@ compile_subscript(
                return FAIL;
            // dictionary member: dict.name
            p = *arg;
-           if (eval_isnamec1(*p))
+           if (eval_isdictc(*p))
                while (eval_isnamec(*p))
                    MB_PTR_ADV(p);
            if (p == *arg)