# HG changeset patch # User Bram Moolenaar # Date 1593260104 -7200 # Node ID 2f8b0812819f13f80b4ce8b0525615846d0f1e58 # Parent 3b26a83c36c3b460745c3ac9267e7179224b8503 patch 8.2.1068: Vim9: no line break allowed inside a dict Commit: https://github.com/vim/vim/commit/8ea9390b78da9e34a20e7418712921397c0c1989 Author: Bram Moolenaar Date: Sat Jun 27 14:11:53 2020 +0200 patch 8.2.1068: Vim9: no line break allowed inside a dict Problem: Vim9: no line break allowed inside a dict. Solution: Handle line break inside a dict in Vim9 script. diff --git a/src/dict.c b/src/dict.c --- a/src/dict.c +++ b/src/dict.c @@ -792,10 +792,10 @@ get_literal_key(char_u **arg, typval_T * * Return OK or FAIL. Returns NOTDONE for {expr}. */ int -eval_dict(char_u **arg, typval_T *rettv, int flags, int literal) +eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) { - int evaluate = flags & EVAL_EVALUATE; - evalarg_T evalarg; + int evaluate = evalarg == NULL ? FALSE + : evalarg->eval_flags & EVAL_EVALUATE; dict_T *d = NULL; typval_T tvkey; typval_T tv; @@ -804,9 +804,8 @@ eval_dict(char_u **arg, typval_T *rettv, char_u *start = skipwhite(*arg + 1); char_u buf[NUMBUFLEN]; int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9; - - CLEAR_FIELD(evalarg); - evalarg.eval_flags = flags; + int had_comma; + int getnext; /* * First check if it's not a curly-braces thing: {expr}. @@ -833,11 +832,14 @@ eval_dict(char_u **arg, typval_T *rettv, tv.v_type = VAR_UNKNOWN; *arg = skipwhite(*arg + 1); + eval_next_non_blank(*arg, evalarg, &getnext); + if (getnext) + *arg = eval_next_line(evalarg); while (**arg != '}' && **arg != NUL) { if ((literal ? get_literal_key(arg, &tvkey) - : eval1(arg, &tvkey, &evalarg)) == FAIL) // recursive! + : eval1(arg, &tvkey, evalarg)) == FAIL) // recursive! goto failret; if (**arg != ':') @@ -857,9 +859,17 @@ eval_dict(char_u **arg, typval_T *rettv, goto failret; } } + if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1])) + { + semsg(_(e_white_after), ":"); + goto failret; + } *arg = skipwhite(*arg + 1); - if (eval1(arg, &tv, &evalarg) == FAIL) // recursive! + eval_next_non_blank(*arg, evalarg, &getnext); + if (getnext) + *arg = eval_next_line(evalarg); + if (eval1(arg, &tv, evalarg) == FAIL) // recursive! { if (evaluate) clear_tv(&tvkey); @@ -887,15 +897,30 @@ eval_dict(char_u **arg, typval_T *rettv, } clear_tv(&tvkey); + // the comma must come after the value + had_comma = **arg == ','; + if (had_comma) + { + if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1])) + { + semsg(_(e_white_after), ","); + goto failret; + } + *arg = skipwhite(*arg + 1); + } + + // the "}" can be on the next line + eval_next_non_blank(*arg, evalarg, &getnext); + if (getnext) + *arg = eval_next_line(evalarg); if (**arg == '}') break; - if (**arg != ',') + if (!had_comma) { if (evaluate) semsg(_(e_missing_dict_comma), *arg); goto failret; } - *arg = skipwhite(*arg + 1); } if (**arg != '}') diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -2787,7 +2787,7 @@ eval7( case '#': if ((*arg)[1] == '{') { ++*arg; - ret = eval_dict(arg, rettv, flags, TRUE); + ret = eval_dict(arg, rettv, evalarg, TRUE); } else ret = NOTDONE; @@ -2799,7 +2799,7 @@ eval7( */ case '{': ret = get_lambda_tv(arg, rettv, evaluate); if (ret == NOTDONE) - ret = eval_dict(arg, rettv, flags, FALSE); + ret = eval_dict(arg, rettv, evalarg, FALSE); break; /* diff --git a/src/proto/dict.pro b/src/proto/dict.pro --- a/src/proto/dict.pro +++ b/src/proto/dict.pro @@ -32,7 +32,7 @@ varnumber_T dict_get_number(dict_T *d, c varnumber_T dict_get_number_def(dict_T *d, char_u *key, int def); varnumber_T dict_get_number_check(dict_T *d, char_u *key); char_u *dict2string(typval_T *tv, int copyID, int restore_copyID); -int eval_dict(char_u **arg, typval_T *rettv, int evaluate, int literal); +int eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal); void dict_extend(dict_T *d1, dict_T *d2, char_u *action); dictitem_T *dict_lookup(hashitem_T *hi); int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive); diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1002,6 +1002,12 @@ def Test_expr7_list_vim9script() assert_equal([11, 22], l) END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let l = [11,22] + END + CheckScriptFailure(lines, 'E1069:') enddef def Test_expr7_lambda() @@ -1034,6 +1040,40 @@ def Test_expr7_dict() call CheckDefExecFailure(["let x = g:dict_empty.member"], 'E716:') enddef +def Test_expr7_dict_vim9script() + let lines =<< trim END + vim9script + let d = { + 'one': + 1, + 'two': 2, + } + assert_equal({'one': 1, 'two': 2}, d) + END + CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let d = #{one: 1, + two: 2, + } + assert_equal({'one': 1, 'two': 2}, d) + END + CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let d = #{one:1, two: 2} + END + CheckScriptFailure(lines, 'E1069:') + + lines =<< trim END + vim9script + let d = #{one: 1,two: 2} + END + CheckScriptFailure(lines, 'E1069:') +enddef + def Test_expr_member() assert_equal(1, g:dict_one.one) let d: dict = g:dict_one diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 1068, +/**/ 1067, /**/ 1066, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2996,7 +2996,7 @@ to_name_const_end(char_u *arg) { // Can be "#{a: 1}->Func()". ++p; - if (eval_dict(&p, &rettv, 0, TRUE) == FAIL) + if (eval_dict(&p, &rettv, NULL, TRUE) == FAIL) p = arg; } else if (p == arg && *arg == '{') @@ -3006,7 +3006,7 @@ to_name_const_end(char_u *arg) // Can be "{x -> ret}()". // Can be "{'a': 1}->Func()". if (ret == NOTDONE) - ret = eval_dict(&p, &rettv, 0, FALSE); + ret = eval_dict(&p, &rettv, NULL, FALSE); if (ret != OK) p = arg; }