1
0
forked from aniani/vim

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)
This commit is contained in:
Bram Moolenaar
2020-06-21 16:58:13 +02:00
parent e55b1c098d
commit 23c5527373
3 changed files with 89 additions and 56 deletions

View File

@@ -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])

View File

@@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1029,
/**/
1028,
/**/

View File

@@ -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;