changeset 20955:396fe712eb0f v8.2.1029

patch 8.2.1029: Vim9: cannot chain function calls with -> at line start Commit: https://github.com/vim/vim/commit/23c55273739b2fb09912140e2e03a4b8ff15dd04 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 21 16:58:13 2020 +0200 patch 8.2.1029: Vim9: cannot chain function calls with -> at line start Problem: Vim9: cannot chain function calls with -> at line start. Solution: Peek ahead for a following line starting with "->". (closes https://github.com/vim/vim/issues/6306)
author Bram Moolenaar <Bram@vim.org>
date Sun, 21 Jun 2020 17:00:04 +0200
parents fef8406c5c10
children be36cdf5d8a0
files src/testdir/test_vim9_expr.vim src/version.c src/vim9compile.c
diffstat 3 files changed, 89 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -1036,6 +1036,24 @@ def Test_expr7_subscript_linebreak()
   	map('string(v:key)')
   assert_equal(['0', '1', '2'], l)
 
+  l = range
+  	->map('string(v:key)')
+  assert_equal(['0', '1', '2'], l)
+
+  l = range # comment
+  	->map('string(v:key)')
+  assert_equal(['0', '1', '2'], l)
+
+  l = range
+
+  	->map('string(v:key)')
+  assert_equal(['0', '1', '2'], l)
+
+  l = range
+	# comment
+  	->map('string(v:key)')
+  assert_equal(['0', '1', '2'], l)
+
   assert_equal('1', l[
 	1])
 
--- 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 */
 /**/
+    1029,
+/**/
     1028,
 /**/
     1027,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2381,11 +2381,42 @@ free_imported(cctx_T *cctx)
 }
 
 /*
+ * Return TRUE if "p" points at a "#" but not at "#{".
+ */
+    static int
+comment_start(char_u *p)
+{
+    return p[0] == '#' && p[1] != '{';
+}
+
+/*
+ * Return a pointer to the next line that isn't empty or only contains a
+ * comment. Skips over white space.
+ * Returns NULL if there is none.
+ */
+    static char_u *
+peek_next_line(cctx_T *cctx)
+{
+    int lnum = cctx->ctx_lnum;
+
+    while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
+    {
+	char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
+	char_u *p = skipwhite(line);
+
+	if (*p != NUL && !comment_start(p))
+	    return p;
+    }
+    return NULL;
+}
+
+/*
  * Get the next line of the function from "cctx".
+ * Skips over empty lines.  Skips over comment lines if "skip_comment" is TRUE.
  * Returns NULL when at the end.
  */
     static char_u *
-next_line_from_context(cctx_T *cctx)
+next_line_from_context(cctx_T *cctx, int skip_comment)
 {
     char_u	*line;
 
@@ -2400,20 +2431,12 @@ next_line_from_context(cctx_T *cctx)
 	line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
 	cctx->ctx_line_start = line;
 	SOURCING_LNUM = cctx->ctx_lnum + 1;
-    } while (line == NULL || *skipwhite(line) == NUL);
+    } while (line == NULL || *skipwhite(line) == NUL
+			  || (skip_comment && comment_start(skipwhite(line))));
     return line;
 }
 
 /*
- * Return TRUE if "p" points at a "#" but not at "#{".
- */
-    static int
-comment_start(char_u *p)
-{
-    return p[0] == '#' && p[1] != '{';
-}
-
-/*
  * If "*arg" is at the end of the line, advance to the next line.
  * Also when "whitep" points to white space and "*arg" is on a "#".
  * Return FAIL if beyond the last line, "*arg" is unmodified then.
@@ -2423,7 +2446,7 @@ may_get_next_line(char_u *whitep, char_u
 {
     if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
     {
-	char_u *next = next_line_from_context(cctx);
+	char_u *next = next_line_from_context(cctx, TRUE);
 
 	if (next == NULL)
 	    return FAIL;
@@ -2752,14 +2775,8 @@ compile_arguments(char_u **arg, cctx_T *
 
     for (;;)
     {
-	while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
-	{
-	    p = next_line_from_context(cctx);
-	    if (p == NULL)
-		goto failret;
-	    whitep = (char_u *)" ";
-	    p = skipwhite(p);
-	}
+	if (may_get_next_line(whitep, &p, cctx) == FAIL)
+	    goto failret;
 	if (*p == ')')
 	{
 	    *arg = p + 1;
@@ -2986,16 +3003,10 @@ compile_list(char_u **arg, cctx_T *cctx)
 
     for (;;)
     {
-	while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
+	if (may_get_next_line(whitep, &p, cctx) == FAIL)
 	{
-	    p = next_line_from_context(cctx);
-	    if (p == NULL)
-	    {
-		semsg(_(e_list_end), *arg);
-		return FAIL;
-	    }
-	    whitep = (char_u *)" ";
-	    p = skipwhite(p);
+	    semsg(_(e_list_end), *arg);
+	    return FAIL;
 	}
 	if (*p == ']')
 	{
@@ -3112,14 +3123,10 @@ compile_dict(char_u **arg, cctx_T *cctx,
     {
 	char_u *key = NULL;
 
-	while (**arg == NUL || (literal && **arg == '"')
-			      || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
+	if (may_get_next_line(whitep, arg, cctx) == FAIL)
 	{
-	    *arg = next_line_from_context(cctx);
-	    if (*arg == NULL)
-		goto failret;
-	    whitep = (char_u *)" ";
-	    *arg = skipwhite(*arg);
+	    *arg = NULL;
+	    goto failret;
 	}
 
 	if (**arg == '}')
@@ -3179,13 +3186,10 @@ compile_dict(char_u **arg, cctx_T *cctx,
 
 	whitep = *arg + 1;
 	*arg = skipwhite(*arg + 1);
-	while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
+	if (may_get_next_line(whitep, arg, cctx) == FAIL)
 	{
-	    *arg = next_line_from_context(cctx);
-	    if (*arg == NULL)
-		goto failret;
-	    whitep = (char_u *)" ";
-	    *arg = skipwhite(*arg);
+	    *arg = NULL;
+	    goto failret;
 	}
 
 	if (compile_expr0(arg, cctx) == FAIL)
@@ -3193,15 +3197,11 @@ compile_dict(char_u **arg, cctx_T *cctx,
 	++count;
 
 	whitep = *arg;
-	p = skipwhite(*arg);
-	while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
+	*arg = skipwhite(*arg);
+	if (may_get_next_line(whitep, arg, cctx) == FAIL)
 	{
-	    *arg = next_line_from_context(cctx);
-	    if (*arg == NULL)
-		goto failret;
-	    whitep = (char_u *)" ";
-	    *arg = skipwhite(*arg);
-	    p = *arg;
+	    *arg = NULL;
+	    goto failret;
 	}
 	if (**arg == '}')
 	    break;
@@ -3506,6 +3506,24 @@ compile_subscript(
 {
     for (;;)
     {
+	char_u *p = skipwhite(*arg);
+
+	if (*p == NUL || (VIM_ISWHITE(**arg) && comment_start(p)))
+	{
+	    char_u *next = peek_next_line(cctx);
+
+	    // If a following line starts with "->{" or "->X" advance to that
+	    // line, so that a line break before "->" is allowed.
+	    if (next != NULL && next[0] == '-' && next[1] == '>'
+		    && (next[2] == '{' || ASCII_ISALPHA(next[2])))
+	    {
+		next = next_line_from_context(cctx, TRUE);
+		if (next == NULL)
+		    return FAIL;
+		*arg = skipwhite(next);
+	    }
+	}
+
 	if (**arg == '(')
 	{
 	    garray_T    *stack = &cctx->ctx_type_stack;
@@ -3526,8 +3544,6 @@ compile_subscript(
 	}
 	else if (**arg == '-' && (*arg)[1] == '>')
 	{
-	    char_u *p;
-
 	    if (generate_ppconst(cctx, ppconst) == FAIL)
 		return FAIL;
 
@@ -3570,7 +3586,6 @@ compile_subscript(
 	{
 	    garray_T	*stack = &cctx->ctx_type_stack;
 	    type_T	**typep;
-	    char_u	*p;
 
 	    // list index: list[123]
 	    // dict member: dict[key]
@@ -3618,8 +3633,6 @@ compile_subscript(
 	}
 	else if (**arg == '.' && (*arg)[1] != '.')
 	{
-	    char_u *p;
-
 	    if (generate_ppconst(cctx, ppconst) == FAIL)
 		return FAIL;
 
@@ -6696,7 +6709,7 @@ compile_def_function(ufunc_T *ufunc, int
 	}
 	else
 	{
-	    line = next_line_from_context(&cctx);
+	    line = next_line_from_context(&cctx, FALSE);
 	    if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
 		// beyond the last line
 		break;