# HG changeset patch # User Bram Moolenaar # Date 1592751604 -7200 # Node ID 396fe712eb0fd851e581e851aa3692873a997df5 # Parent fef8406c5c101f5ace86742ba8cdfd907fa7d576 patch 8.2.1029: Vim9: cannot chain function calls with -> at line start Commit: https://github.com/vim/vim/commit/23c55273739b2fb09912140e2e03a4b8ff15dd04 Author: Bram Moolenaar 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) 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 @@ -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]) 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 */ /**/ + 1029, +/**/ 1028, /**/ 1027, diff --git a/src/vim9compile.c b/src/vim9compile.c --- 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;