summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-07-27 21:43:28 +0200
committerBram Moolenaar <Bram@vim.org>2020-07-27 21:43:28 +0200
commitb13ab99908097d54e21ab5adad22f4ad2a8ec688 (patch)
tree8b35ffaf45b3ed9b21bce9bc8f6422b31564be69
parent622b3568fa1baf07671d31390815fb0a55a99891 (diff)
downloadvim-git-b13ab99908097d54e21ab5adad22f4ad2a8ec688.tar.gz
patch 8.2.1306: checking for first character of dict key is inconsistentv8.2.1306
Problem: Checking for first character of dict key is inconsistent. Solution: Add eval_isdictc(). (closes #6546)
-rw-r--r--src/eval.c21
-rw-r--r--src/proto/eval.pro1
-rw-r--r--src/testdir/test_let.vim2
-rw-r--r--src/testdir/test_listdict.vim7
-rw-r--r--src/testdir/test_vim9_expr.vim13
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c4
7 files changed, 40 insertions, 10 deletions
diff --git a/src/eval.c b/src/eval.c
index 6d3d19ee8..81913c7a3 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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])))))
{
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index 5d04e01ac..a528d3e43 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -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);
diff --git a/src/testdir/test_let.vim b/src/testdir/test_let.vim
index 9a399e8f3..017b2a4a4 100644
--- a/src/testdir/test_let.vim
+++ b/src/testdir/test_let.vim
@@ -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:')
diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim
index b06484699..beeda2f5b 100644
--- a/src/testdir/test_listdict.vim
+++ b/src/testdir/test_listdict.vim
@@ -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 = {}
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index d7072f34b..5b46c32f9 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -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'
])
diff --git a/src/version.c b/src/version.c
index ec702330b..a87cc89d3 100644
--- 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 */
/**/
+ 1306,
+/**/
1305,
/**/
1304,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 8efb1f672..1ed321146 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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)