mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 9.0.1505: error when heredoc content looks like heredoc
Problem: Error when heredoc content looks like heredoc. Solution: Handle curly expressions. (closes #12325)
This commit is contained in:
@@ -6581,7 +6581,7 @@ find_name_end(
|
|||||||
int br_nest = 0;
|
int br_nest = 0;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int len;
|
int len;
|
||||||
int vim9script = in_vim9script();
|
int allow_curly = (flags & FNE_ALLOW_CURLY) || !in_vim9script();
|
||||||
|
|
||||||
if (expr_start != NULL)
|
if (expr_start != NULL)
|
||||||
{
|
{
|
||||||
@@ -6591,12 +6591,12 @@ find_name_end(
|
|||||||
|
|
||||||
// Quick check for valid starting character.
|
// Quick check for valid starting character.
|
||||||
if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg)
|
if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg)
|
||||||
&& (*arg != '{' || vim9script))
|
&& (*arg != '{' || !allow_curly))
|
||||||
return arg;
|
return arg;
|
||||||
|
|
||||||
for (p = arg; *p != NUL
|
for (p = arg; *p != NUL
|
||||||
&& (eval_isnamec(*p)
|
&& (eval_isnamec(*p)
|
||||||
|| (*p == '{' && !vim9script)
|
|| (*p == '{' && allow_curly)
|
||||||
|| ((flags & FNE_INCL_BR) && (*p == '['
|
|| ((flags & FNE_INCL_BR) && (*p == '['
|
||||||
|| (*p == '.' && eval_isdictc(p[1]))))
|
|| (*p == '.' && eval_isdictc(p[1]))))
|
||||||
|| mb_nest != 0
|
|| mb_nest != 0
|
||||||
@@ -6637,7 +6637,7 @@ find_name_end(
|
|||||||
--br_nest;
|
--br_nest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (br_nest == 0 && !vim9script)
|
if (br_nest == 0 && allow_curly)
|
||||||
{
|
{
|
||||||
if (*p == '{')
|
if (*p == '{')
|
||||||
{
|
{
|
||||||
|
@@ -337,7 +337,43 @@ func Test_let_heredoc_fails()
|
|||||||
call assert_report('No exception thrown')
|
call assert_report('No exception thrown')
|
||||||
catch /E488:/
|
catch /E488:/
|
||||||
catch
|
catch
|
||||||
call assert_report("Caught exception: " .. v:exception)
|
call assert_report('Caught exception: ' .. v:exception)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
let &commentstring =<< trim TEXT
|
||||||
|
change
|
||||||
|
insert
|
||||||
|
append
|
||||||
|
TEXT
|
||||||
|
call assert_report('No exception thrown')
|
||||||
|
catch /E730:/
|
||||||
|
catch
|
||||||
|
call assert_report('Caught exception: ' .. v:exception)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
let $SOME_ENV_VAR =<< trim TEXT
|
||||||
|
change
|
||||||
|
insert
|
||||||
|
append
|
||||||
|
TEXT
|
||||||
|
call assert_report('No exception thrown')
|
||||||
|
catch /E730:/
|
||||||
|
catch
|
||||||
|
call assert_report('Caught exception: ' .. v:exception)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
let @r =<< trim TEXT
|
||||||
|
change
|
||||||
|
insert
|
||||||
|
append
|
||||||
|
TEXT
|
||||||
|
call assert_report('No exception thrown')
|
||||||
|
catch /E730:/
|
||||||
|
catch
|
||||||
|
call assert_report('Caught exception: ' .. v:exception)
|
||||||
endtry
|
endtry
|
||||||
|
|
||||||
let text =<< trim END
|
let text =<< trim END
|
||||||
@@ -506,6 +542,32 @@ E
|
|||||||
z
|
z
|
||||||
END
|
END
|
||||||
call assert_equal([' x', ' \y', ' z'], [a, b, c])
|
call assert_equal([' x', ' \y', ' z'], [a, b, c])
|
||||||
|
|
||||||
|
" unpack assignment without whitespace
|
||||||
|
let[a,b,c]=<<END
|
||||||
|
change
|
||||||
|
insert
|
||||||
|
append
|
||||||
|
END
|
||||||
|
call assert_equal(['change', 'insert', 'append'], [a, b, c])
|
||||||
|
|
||||||
|
" curly braces name and list slice assignment
|
||||||
|
let foo_3_bar = ['', '', '']
|
||||||
|
let foo_{1 + 2}_bar[ : ] =<< END
|
||||||
|
change
|
||||||
|
insert
|
||||||
|
append
|
||||||
|
END
|
||||||
|
call assert_equal(['change', 'insert', 'append'], foo_3_bar)
|
||||||
|
|
||||||
|
" dictionary key containing brackets and spaces
|
||||||
|
let d = {'abc] 123': 'baz'}
|
||||||
|
let d[d['abc] 123'] .. '{'] =<< END
|
||||||
|
change
|
||||||
|
insert
|
||||||
|
append
|
||||||
|
END
|
||||||
|
call assert_equal(['change', 'insert', 'append'], d['baz{'])
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test for evaluating Vim expressions in a heredoc using {expr}
|
" Test for evaluating Vim expressions in a heredoc using {expr}
|
||||||
|
@@ -1872,6 +1872,57 @@ def Test_heredoc()
|
|||||||
END
|
END
|
||||||
v9.CheckDefAndScriptSuccess(lines)
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
|
# assign heredoc to variable with type
|
||||||
|
lines =<< trim END
|
||||||
|
var text: list<string> =<< trim TEXT
|
||||||
|
var foo =<< trim FOO
|
||||||
|
TEXT
|
||||||
|
assert_equal(['var foo =<< trim FOO'], text)
|
||||||
|
END
|
||||||
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
|
# extra whitespace before type is allowed
|
||||||
|
lines =<< trim END
|
||||||
|
var text: list<string> =<< trim TEXT
|
||||||
|
var foo =<< trim FOO
|
||||||
|
TEXT
|
||||||
|
assert_equal(['var foo =<< trim FOO'], text)
|
||||||
|
END
|
||||||
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
|
# missing whitespace before type is an error
|
||||||
|
lines =<< trim END
|
||||||
|
var text:list<string> =<< trim TEXT
|
||||||
|
var foo =<< trim FOO
|
||||||
|
TEXT
|
||||||
|
assert_equal(['var foo =<< trim FOO'], text)
|
||||||
|
END
|
||||||
|
v9.CheckDefAndScriptFailure(lines, 'E1069:')
|
||||||
|
|
||||||
|
# assign heredoc to list slice
|
||||||
|
lines =<< trim END
|
||||||
|
var text = ['']
|
||||||
|
text[ : ] =<< trim TEXT
|
||||||
|
var foo =<< trim FOO
|
||||||
|
TEXT
|
||||||
|
assert_equal(['var foo =<< trim FOO'], text)
|
||||||
|
END
|
||||||
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
|
# assign heredoc to curly braces name in legacy function in Vim9 script
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
func Func()
|
||||||
|
let foo_3_bar = ['']
|
||||||
|
let foo_{1 + 2}_bar[ : ] =<< trim TEXT
|
||||||
|
var foo =<< trim FOO
|
||||||
|
TEXT
|
||||||
|
call assert_equal(['var foo =<< trim FOO'], foo_3_bar)
|
||||||
|
endfunc
|
||||||
|
Func()
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
|
||||||
v9.CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
|
v9.CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
|
||||||
v9.CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
|
v9.CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
|
||||||
|
|
||||||
|
@@ -1143,7 +1143,7 @@ get_function_body(
|
|||||||
skip_until = vim_strnsave(p, skiptowhite(p) - p);
|
skip_until = vim_strnsave(p, skiptowhite(p) - p);
|
||||||
getline_options = GETLINE_NONE;
|
getline_options = GETLINE_NONE;
|
||||||
is_heredoc = TRUE;
|
is_heredoc = TRUE;
|
||||||
if (eap->cmdidx == CMD_def && nesting == 0)
|
if (vim9_function && nesting == 0)
|
||||||
heredoc_concat_len = newlines->ga_len + 1;
|
heredoc_concat_len = newlines->ga_len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1153,23 +1153,20 @@ get_function_body(
|
|||||||
// and ":cmd [a, b] =<< [trim] EOF"
|
// and ":cmd [a, b] =<< [trim] EOF"
|
||||||
// and "lines =<< [trim] EOF" for Vim9
|
// and "lines =<< [trim] EOF" for Vim9
|
||||||
// Where "cmd" can be "let", "var", "final" or "const".
|
// Where "cmd" can be "let", "var", "final" or "const".
|
||||||
arg = skipwhite(skiptowhite(p));
|
arg = p;
|
||||||
if (*arg == '[')
|
if (checkforcmd(&arg, "let", 2)
|
||||||
arg = vim_strchr(arg, ']');
|
|| checkforcmd(&arg, "var", 3)
|
||||||
if (arg != NULL)
|
|| checkforcmd(&arg, "final", 5)
|
||||||
|
|| checkforcmd(&arg, "const", 5)
|
||||||
|
|| vim9_function)
|
||||||
{
|
{
|
||||||
int found = (eap->cmdidx == CMD_def && arg[0] == '='
|
while (vim_strchr((char_u *)"$@&", *arg) != NULL)
|
||||||
&& arg[1] == '<' && arg[2] =='<');
|
++arg;
|
||||||
|
arg = skipwhite(find_name_end(arg, NULL, NULL,
|
||||||
if (!found)
|
FNE_INCL_BR | FNE_ALLOW_CURLY));
|
||||||
// skip over the argument after "cmd"
|
if (vim9_function && *arg == ':')
|
||||||
arg = skipwhite(skiptowhite(arg));
|
arg = skipwhite(skip_type(skipwhite(arg + 1), FALSE));
|
||||||
if (found || (arg[0] == '=' && arg[1] == '<'
|
if (arg[0] == '=' && arg[1] == '<' && arg[2] =='<')
|
||||||
&& arg[2] =='<'
|
|
||||||
&& (checkforcmd(&p, "let", 2)
|
|
||||||
|| checkforcmd(&p, "var", 3)
|
|
||||||
|| checkforcmd(&p, "final", 5)
|
|
||||||
|| checkforcmd(&p, "const", 5))))
|
|
||||||
{
|
{
|
||||||
p = skipwhite(arg + 3);
|
p = skipwhite(arg + 3);
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1505,
|
||||||
/**/
|
/**/
|
||||||
1504,
|
1504,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2758,6 +2758,7 @@ typedef char *(*opt_did_set_cb_T)(optset_T *args);
|
|||||||
// flags for find_name_end()
|
// flags for find_name_end()
|
||||||
#define FNE_INCL_BR 1 // include [] in name
|
#define FNE_INCL_BR 1 // include [] in name
|
||||||
#define FNE_CHECK_START 2 // check name starts with valid character
|
#define FNE_CHECK_START 2 // check name starts with valid character
|
||||||
|
#define FNE_ALLOW_CURLY 4 // always allow curly braces name
|
||||||
|
|
||||||
// BSD is supposed to cover FreeBSD and similar systems.
|
// BSD is supposed to cover FreeBSD and similar systems.
|
||||||
#if (defined(SUN_SYSTEM) || defined(BSD) || defined(__FreeBSD_kernel__)) \
|
#if (defined(SUN_SYSTEM) || defined(BSD) || defined(__FreeBSD_kernel__)) \
|
||||||
|
Reference in New Issue
Block a user