From 23c55273739b2fb09912140e2e03a4b8ff15dd04 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 21 Jun 2020 16:58:13 +0200 Subject: [PATCH] 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 #6306) --- src/testdir/test_vim9_expr.vim | 18 +++++ src/version.c | 2 + src/vim9compile.c | 125 ++++++++++++++++++--------------- 3 files changed, 89 insertions(+), 56 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index f87e920b2..b46e04bc8 100644 --- 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 index 77fdac139..b4e74825e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1029, /**/ 1028, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 3b021afdc..871e70736 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2380,12 +2380,43 @@ free_imported(cctx_T *cctx) ga_clear(&cctx->ctx_imports); } +/* + * 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,19 +2431,11 @@ 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 "#". @@ -2423,7 +2446,7 @@ may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx) { 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 *cctx, int *argcount) 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, int literal) { 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, int literal) 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, int literal) ++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 set_return_type, cctx_T *outer_cctx) } 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; -- 2.40.0