]> granicus.if.org Git - vim/commitdiff
patch 8.2.1110: Vim9: line continuation does not work in function arguments v8.2.1110
authorBram Moolenaar <Bram@vim.org>
Wed, 1 Jul 2020 15:28:33 +0000 (17:28 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 1 Jul 2020 15:28:33 +0000 (17:28 +0200)
Problem:    Vim9: line continuation does not work in function arguments.
Solution:   Pass "evalarg" to get_func_tv().  Fix seeing double quoted string
            as comment.

src/dict.c
src/eval.c
src/ex_eval.c
src/list.c
src/proto/eval.pro
src/proto/userfunc.pro
src/testdir/test_vim9_expr.vim
src/testdir/test_vim9_func.vim
src/userfunc.c
src/version.c

index 079eb3e11e4ef79cd28c925acc111015a8491e12..53824f75d6396a6f7290e18247c80c6ee20d3d35 100644 (file)
@@ -830,7 +830,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal)
     tvkey.v_type = VAR_UNKNOWN;
     tv.v_type = VAR_UNKNOWN;
 
-    *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
+    *arg = skipwhite_and_linebreak_keep_string(*arg + 1, evalarg);
     while (**arg != '}' && **arg != NUL)
     {
        if ((literal
@@ -862,7 +862,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal)
            goto failret;
        }
 
-       *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
+       *arg = skipwhite_and_linebreak_keep_string(*arg + 1, evalarg);
        if (eval1(arg, &tv, evalarg) == FAIL)   // recursive!
        {
            if (evaluate)
@@ -904,7 +904,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal)
        }
 
        // the "}" can be on the next line
-       *arg = skipwhite_and_linebreak(*arg, evalarg);
+       *arg = skipwhite_and_linebreak_keep_string(*arg, evalarg);
        if (**arg == '}')
            break;
        if (!had_comma)
index 5a0aef2c27dc2a7de8bf56ac62ebd6010145b30d..ce255e2b967bf66f4658884c738266d1ef13364d 100644 (file)
@@ -153,7 +153,7 @@ eval_clear(void)
 }
 #endif
 
-    static void
+    void
 fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip)
 {
     CLEAR_FIELD(*evalarg);
@@ -1804,6 +1804,7 @@ pattern_match(char_u *pat, char_u *text, int ic)
     static int
 eval_func(
        char_u      **arg,      // points to "(", will be advanced
+       evalarg_T   *evalarg,
        char_u      *name,
        int         name_len,
        typval_T    *rettv,
@@ -1839,7 +1840,7 @@ eval_func(
        funcexe.evaluate = evaluate;
        funcexe.partial = partial;
        funcexe.basetv = basetv;
-       ret = get_func_tv(s, len, rettv, arg, &funcexe);
+       ret = get_func_tv(s, len, rettv, arg, evalarg, &funcexe);
     }
     vim_free(s);
 
@@ -1917,6 +1918,9 @@ eval_next_line(evalarg_T *evalarg)
     return skipwhite(line);
 }
 
+/*
+ * Call eval_next_non_blank() and get the next line if needed.
+ */
     char_u *
 skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg)
 {
@@ -1929,6 +1933,20 @@ skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg)
     return p;
 }
 
+/*
+ * Call eval_next_non_blank() and get the next line if needed, but not when a
+ * double quote follows.  Used inside an expression.
+ */
+    char_u *
+skipwhite_and_linebreak_keep_string(char_u *arg, evalarg_T *evalarg)
+{
+    char_u  *p = skipwhite(arg);
+
+    if (*p == '"')
+       return p;
+    return skipwhite_and_linebreak(arg, evalarg);
+}
+
 /*
  * After using "evalarg" filled from "eap" free the memory.
  */
@@ -2995,7 +3013,7 @@ eval7(
        else
        {
            if (**arg == '(')           // recursive!
-               ret = eval_func(arg, s, len, rettv, flags, NULL);
+               ret = eval_func(arg, evalarg, s, len, rettv, flags, NULL);
            else if (flags & EVAL_CONSTANT)
                ret = FAIL;
            else if (evaluate)
@@ -3106,6 +3124,7 @@ eval7_leader(
     static int
 call_func_rettv(
        char_u      **arg,
+       evalarg_T   *evalarg,
        typval_T    *rettv,
        int         evaluate,
        dict_T      *selfdict,
@@ -3142,7 +3161,7 @@ call_func_rettv(
     funcexe.partial = pt;
     funcexe.selfdict = selfdict;
     funcexe.basetv = basetv;
-    ret = get_func_tv(s, -1, rettv, arg, &funcexe);
+    ret = get_func_tv(s, -1, rettv, arg, evalarg, &funcexe);
 
     // Clear the funcref afterwards, so that deleting it while
     // evaluating the arguments is possible (see test55).
@@ -3189,7 +3208,7 @@ eval_lambda(
        ret = FAIL;
     }
     else
-       ret = call_func_rettv(arg, rettv, evaluate, NULL, &base);
+       ret = call_func_rettv(arg, evalarg, rettv, evaluate, NULL, &base);
 
     // Clear the funcref afterwards, so that deleting it while
     // evaluating the arguments is possible (see test55).
@@ -3208,7 +3227,7 @@ eval_lambda(
 eval_method(
     char_u     **arg,
     typval_T   *rettv,
-    int                evaluate,
+    evalarg_T  *evalarg,
     int                verbose)        // give error messages
 {
     char_u     *name;
@@ -3216,6 +3235,8 @@ eval_method(
     char_u     *alias;
     typval_T   base = *rettv;
     int                ret;
+    int                evaluate = evalarg != NULL
+                                     && (evalarg->eval_flags & EVAL_EVALUATE);
 
     // Skip over the ->.
     *arg += 2;
@@ -3247,7 +3268,7 @@ eval_method(
            ret = FAIL;
        }
        else
-           ret = eval_func(arg, name, len, rettv,
+           ret = eval_func(arg, evalarg, name, len, rettv,
                                          evaluate ? EVAL_EVALUATE : 0, &base);
     }
 
@@ -5035,7 +5056,8 @@ handle_subscript(
     {
        if (**arg == '(')
        {
-           ret = call_func_rettv(arg, rettv, evaluate, selfdict, NULL);
+           ret = call_func_rettv(arg, evalarg, rettv, evaluate,
+                                                              selfdict, NULL);
 
            // Stop the expression evaluation when immediately aborting on
            // error, or when an interrupt occurred or an exception was thrown
@@ -5058,7 +5080,7 @@ handle_subscript(
                    ret = eval_lambda(arg, rettv, evalarg, verbose);
                else
                    // expr->name()
-                   ret = eval_method(arg, rettv, evaluate, verbose);
+                   ret = eval_method(arg, rettv, evalarg, verbose);
            }
        }
        else // **arg == '[' || **arg == '.'
index fea8c7fd6bd9fd8a39280750d8bd054d76d9ad6d..061bd1a6495e3901419b923ac9f25868063146d4 100644 (file)
@@ -897,13 +897,7 @@ ex_eval(exarg_T *eap)
     typval_T   tv;
     evalarg_T  evalarg;
 
-    CLEAR_FIELD(evalarg);
-    evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
-    if (getline_equal(eap->getline, eap->cookie, getsourceline))
-    {
-       evalarg.eval_getline = eap->getline;
-       evalarg.eval_cookie = eap->cookie;
-    }
+    fill_evalarg_from_eap(&evalarg, eap, eap->skip);
 
     if (eval0(eap->arg, &tv, eap, &evalarg) == OK)
        clear_tv(&tv);
index ffcffa9f0c5cbafb4d80ed88139ea82d2ec88826..2bea55e02fea8eabcb42fe65941e1b8213a3604e 100644 (file)
@@ -1177,7 +1177,7 @@ get_list_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error)
            return FAIL;
     }
 
-    *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
+    *arg = skipwhite_and_linebreak_keep_string(*arg + 1, evalarg);
     while (**arg != ']' && **arg != NUL)
     {
        if (eval1(arg, &tv, evalarg) == FAIL)   // recursive!
@@ -1207,8 +1207,9 @@ get_list_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error)
            *arg = skipwhite(*arg + 1);
        }
 
-       // the "]" can be on the next line
-       *arg = skipwhite_and_linebreak(*arg, evalarg);
+       // The "]" can be on the next line.  But a double quoted string may
+       // follow, not a comment.
+       *arg = skipwhite_and_linebreak_keep_string(*arg, evalarg);
        if (**arg == ']')
            break;
 
@@ -2356,7 +2357,7 @@ f_insert(typval_T *argvars, typval_T *rettv)
        }
        if (l != NULL)
        {
-           list_insert_tv(l, &argvars[1], item);
+           (void)list_insert_tv(l, &argvars[1], item);
            copy_tv(&argvars[0], rettv);
        }
     }
index 0e9ffeb80843f0523096f93229fa498bb07cb3f8..910fdfd1801300366f8e8fba20b84501d0044a29 100644 (file)
@@ -3,6 +3,7 @@ varnumber_T num_divide(varnumber_T n1, varnumber_T n2);
 varnumber_T num_modulus(varnumber_T n1, varnumber_T n2);
 void eval_init(void);
 void eval_clear(void);
+void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip);
 int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip);
 int eval_expr_valid_arg(typval_T *tv);
 int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv);
@@ -31,6 +32,7 @@ int pattern_match(char_u *pat, char_u *text, int ic);
 char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext);
 char_u *eval_next_line(evalarg_T *evalarg);
 char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg);
+char_u *skipwhite_and_linebreak_keep_string(char_u *arg, evalarg_T *evalarg);
 void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
 int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
 int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
index f69f77d6a4a57851117f0a023a67b53386493cb7..75a1562570b980f2c7a294d9c2d57051099a27c9 100644 (file)
@@ -7,7 +7,7 @@ char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
 int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
 char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
 void emsg_funcname(char *ermsg, char_u *name);
-int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe);
+int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
 char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
 ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
 int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
index bf4f7d2eafe12e171f07dd8e70e6bc5ce82ce212..1f4b254980035b0d3f8eed6332c31e3906e10ae6 100644 (file)
@@ -1099,6 +1099,13 @@ def Test_expr7_dict_vim9script()
   END
   CheckScriptSuccess(lines)
 
+  lines =<< trim END
+      vim9script
+      let d = { "one": "one", "two": "two", }
+      assert_equal({'one': 'one', 'two': 'two'}, d)
+  END
+  CheckScriptSuccess(lines)
+
   lines =<< trim END
       vim9script
       let d = #{one: 1,
index 1fc13c088d142470a31c2ec8c01b0ba972d7a498..6a03eddc1d53e1414dc5484cc79e6b8dcb1a1664 100644 (file)
@@ -353,6 +353,22 @@ def Test_vim9script_call()
     assert_equal('text', var)
     ("some")->MyFunc()
     assert_equal('some', var)
+
+    MyFunc(
+        'continued'
+        )
+    assert_equal('continued',
+            var
+            )
+
+    call MyFunc(
+        'more'
+          ..
+          'lines'
+        )
+    assert_equal(
+        'morelines',
+        var)
   END
   writefile(lines, 'Xcall.vim')
   source Xcall.vim
index 724d1247d9d2e12992af5e3473fe849fbf6e9e00..121079149aeffd019040202fd6a4e2ff1a2bec89 100644 (file)
@@ -601,16 +601,13 @@ get_func_tv(
     int                len,            // length of "name" or -1 to use strlen()
     typval_T   *rettv,
     char_u     **arg,          // argument, pointing to the '('
+    evalarg_T  *evalarg,       // for line continuation
     funcexe_T  *funcexe)       // various values
 {
     char_u     *argp;
     int                ret = OK;
     typval_T   argvars[MAX_FUNC_ARGS + 1];     // vars for arguments
     int                argcount = 0;           // number of arguments found
-    evalarg_T  evalarg;
-
-    CLEAR_FIELD(evalarg);
-    evalarg.eval_flags = funcexe->evaluate ? EVAL_EVALUATE : 0;
 
     /*
      * Get the arguments.
@@ -619,10 +616,12 @@ get_func_tv(
     while (argcount < MAX_FUNC_ARGS - (funcexe->partial == NULL ? 0
                                                  : funcexe->partial->pt_argc))
     {
-       argp = skipwhite(argp + 1);         // skip the '(' or ','
+       // skip the '(' or ',' and possibly line breaks
+       argp = skipwhite_and_linebreak(argp + 1, evalarg);
+
        if (*argp == ')' || *argp == ',' || *argp == NUL)
            break;
-       if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL)
+       if (eval1(&argp, &argvars[argcount], evalarg) == FAIL)
        {
            ret = FAIL;
            break;
@@ -631,6 +630,7 @@ get_func_tv(
        if (*argp != ',')
            break;
     }
+    argp = skipwhite_and_linebreak(argp, evalarg);
     if (*argp == ')')
        ++argp;
     else
@@ -3832,16 +3832,19 @@ ex_call(exarg_T *eap)
     int                failed = FALSE;
     funcdict_T fudi;
     partial_T  *partial = NULL;
+    evalarg_T  evalarg;
 
+    fill_evalarg_from_eap(&evalarg, eap, eap->skip);
     if (eap->skip)
     {
        // trans_function_name() doesn't work well when skipping, use eval0()
        // instead to skip to any following command, e.g. for:
        //   :if 0 | call dict.foo().bar() | endif
        ++emsg_skip;
-       if (eval0(eap->arg, &rettv, eap, NULL) != FAIL)
+       if (eval0(eap->arg, &rettv, eap, &evalarg) != FAIL)
            clear_tv(&rettv);
        --emsg_skip;
+       clear_evalarg(&evalarg, eap);
        return;
     }
 
@@ -3918,7 +3921,7 @@ ex_call(exarg_T *eap)
        funcexe.evaluate = !eap->skip;
        funcexe.partial = partial;
        funcexe.selfdict = fudi.fd_dict;
-       if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL)
+       if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL)
        {
            failed = TRUE;
            break;
@@ -3947,6 +3950,7 @@ ex_call(exarg_T *eap)
     }
     if (eap->skip)
        --emsg_skip;
+    clear_evalarg(&evalarg, eap);
 
     // When inside :try we need to check for following "| catch".
     if (!failed || eap->cstack->cs_trylevel > 0)
index 128fe6c404784fe6973de82e2ce81faa81276617..e7dc813ce2fd4be7ef7d9ce3d6ba8a2a9973a622 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1110,
 /**/
     1109,
 /**/