]> granicus.if.org Git - vim/commitdiff
patch 8.2.0563: Vim9: cannot split a function line v8.2.0563
authorBram Moolenaar <Bram@vim.org>
Sun, 12 Apr 2020 19:53:00 +0000 (21:53 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 12 Apr 2020 19:53:00 +0000 (21:53 +0200)
Problem:    Vim9: cannot split a function line.
Solution:   Continue in next line so long as the function isn't done.

runtime/doc/vim9.txt
src/proto/userfunc.pro
src/testdir/test_vim9_func.vim
src/userfunc.c
src/version.c
src/vim9compile.c

index 1d7aec94602474dd5b9dcde3bda40087287194df..88c35deff50e4e687435705daa5c823448eaa0d1 100644 (file)
@@ -210,6 +210,13 @@ possible AFTER the operators.  For example: >
 Note that "enddef" cannot be used at the start of a continuation line, it ends
 the current function.
 
+It is also possible to split a function header over multiple lines, in between
+arguments: >
+       def MyFunc(
+               text: string,
+               separator = '-'
+               ): string
+
 
 No curly braces expansion ~
 
index 165b04b5e49c5f268a2891b2821098c386898784..2ee3eef6ae8ab0f0cfcf2486debbe67ce9acdc75 100644 (file)
@@ -1,7 +1,7 @@
 /* userfunc.c */
 void func_init(void);
 hashtab_T *func_tbl_get(void);
-int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T *argtypes, int *varargs, garray_T *default_args, int skip);
+int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T *argtypes, int *varargs, garray_T *default_args, int skip, exarg_T *eap, char_u **line_to_free);
 int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
 char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
 void emsg_funcname(char *ermsg, char_u *name);
index a40ac3e99f4ed81e0b22d09e0ce0bcbbbd152e58..38d7c5a5a026a213de745744d9c67d4a414e14bd 100644 (file)
@@ -561,6 +561,22 @@ def Test_func_return_type()
   CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
 enddef
 
+def MultiLine(
+    arg1: string,
+    arg2 = 1234,
+    ...rest: list<string>
+      ): string
+  return arg1 .. arg2 .. join(rest, '-')
+enddef
+
+def Test_multiline()
+  assert_equal('text1234', MultiLine('text'))
+  assert_equal('text777', MultiLine('text', 777))
+  assert_equal('text777one', MultiLine('text', 777, 'one'))
+  assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
+enddef
+
+
 " When using CheckScriptFailure() for the below test, E1010 is generated instead
 " of E1056.
 func Test_E1056_1059()
index 3c15c79c538717cb6503600c34984466eff06166..98e1ec5f2e37520c23c39e0907adab9759d59db9 100644 (file)
@@ -144,7 +144,9 @@ get_function_args(
     garray_T   *argtypes,      // NULL unless using :def
     int                *varargs,
     garray_T   *default_args,
-    int                skip)
+    int                skip,
+    exarg_T    *eap,
+    char_u     **line_to_free)
 {
     int                mustend = FALSE;
     char_u     *arg = *argp;
@@ -168,6 +170,28 @@ get_function_args(
      */
     while (*p != endchar)
     {
+       if (eap != NULL && *p == NUL && eap->getline != NULL)
+       {
+           char_u *theline;
+
+           // End of the line, get the next one.
+           theline = eap->getline(':', eap->cookie, 0, TRUE);
+           if (theline == NULL)
+               break;
+           vim_free(*line_to_free);
+           *line_to_free = theline;
+           p = skipwhite(theline);
+       }
+
+       if (mustend && *p != endchar)
+       {
+           if (!skip)
+               semsg(_(e_invarg2), *argp);
+           break;
+       }
+       if (*p == endchar)
+           break;
+
        if (p[0] == '.' && p[1] == '.' && p[2] == '.')
        {
            if (varargs != NULL)
@@ -241,13 +265,8 @@ get_function_args(
                mustend = TRUE;
        }
        p = skipwhite(p);
-       if (mustend && *p != endchar)
-       {
-           if (!skip)
-               semsg(_(e_invarg2), *argp);
-           break;
-       }
     }
+
     if (*p != endchar)
        goto err_ret;
     ++p;       // skip "endchar"
@@ -323,7 +342,8 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
     ga_init(&newlines);
 
     // First, check if this is a lambda expression. "->" must exist.
-    ret = get_function_args(&start, '-', NULL, NULL, NULL, NULL, TRUE);
+    ret = get_function_args(&start, '-', NULL, NULL, NULL, NULL, TRUE,
+                                                                  NULL, NULL);
     if (ret == FAIL || *start != '>')
        return NOTDONE;
 
@@ -334,7 +354,8 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
        pnewargs = NULL;
     *arg = skipwhite(*arg + 1);
     // TODO: argument types
-    ret = get_function_args(arg, '-', pnewargs, NULL, &varargs, NULL, FALSE);
+    ret = get_function_args(arg, '-', pnewargs, NULL, &varargs, NULL, FALSE,
+                                                                  NULL, NULL);
     if (ret == FAIL || **arg != '>')
        goto errret;
 
@@ -2508,9 +2529,12 @@ ex_function(exarg_T *eap)
            emsg(_("E862: Cannot use g: here"));
     }
 
+    // This may get more lines and make the pointers into the first line
+    // invalid.
     if (get_function_args(&p, ')', &newargs,
                        eap->cmdidx == CMD_def ? &argtypes : NULL,
-                        &varargs, &default_args, eap->skip) == FAIL)
+                        &varargs, &default_args, eap->skip,
+                        eap, &line_to_free) == FAIL)
        goto errret_2;
 
     if (eap->cmdidx == CMD_def)
@@ -2521,9 +2545,15 @@ ex_function(exarg_T *eap)
            ret_type = skipwhite(p + 1);
            p = skip_type(ret_type);
            if (p > ret_type)
+           {
+               ret_type = vim_strnsave(ret_type, (int)(p - ret_type));
                p = skipwhite(p);
+           }
            else
+           {
+               ret_type = NULL;
                semsg(_("E1056: expected a type: %s"), ret_type);
+           }
        }
     }
     else
@@ -3134,6 +3164,7 @@ ret_free:
     vim_free(line_to_free);
     vim_free(fudi.fd_newkey);
     vim_free(name);
+    vim_free(ret_type);
     did_emsg |= saved_did_emsg;
     need_wait_return |= saved_wait_return;
 }
index 44adf49188066ead3fcb18d26a1461e94bd40c45..d43c9d578793abdba108fcf43de371ba162ddfc2 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    563,
 /**/
     562,
 /**/
index 7e7ecb864a5be345ff57cc2fca41516b5a348895..e39ddeecabd75dfda99e6678199502f02cd7a064 100644 (file)
@@ -3275,8 +3275,9 @@ compile_expr7(char_u **arg, cctx_T *cctx)
                        char_u *start = skipwhite(*arg + 1);
 
                        // Find out what comes after the arguments.
+                       // TODO: pass getline function
                        ret = get_function_args(&start, '-', NULL,
-                                                      NULL, NULL, NULL, TRUE);
+                                          NULL, NULL, NULL, TRUE, NULL, NULL);
                        if (ret != FAIL && *start == '>')
                            ret = compile_lambda(arg, cctx);
                        else