0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.2.1227: Vim9: allowing both quoted and # comments is confusing

Problem:    Vim9: allowing both quoted and # comments is confusing.
Solution:   Only support # comments in Vim9 script.
This commit is contained in:
Bram Moolenaar
2020-07-17 20:36:00 +02:00
parent 98af99f2d7
commit f5be8cdb77
9 changed files with 169 additions and 128 deletions

View File

@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2020 Jul 10 *vim9.txt* For Vim version 8.2. Last change: 2020 Jul 17
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -64,20 +64,24 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
Comments starting with # ~ Comments starting with # ~
In Vim script comments start with double quote. That can also be the start of In legacy Vim script comments start with double quote. In Vim9 script
a string, thus in many places it cannot be used. In Vim9 script a comment comments start with #. >
normally starts with #. In Vi this is a command to list text with numbers, # declarations
but you can also use `:number` for that. >
let count = 0 # number of occurrences let count = 0 # number of occurrences
To improve readability there must be a space between the command and the # The reason is that a double quote can also be the start of a string. In many
places, especially halfway an expression with a line break, it's hard to tell
what the meaning is. To avoid confusion only # comments are recognized.
This is the same as in shell scripts and Python programs.
In Vi # is a command to list text with numbers. In Vim9 script you can use
`:number` for that. >
101number
To improve readability there must be a space between a command and the #
that starts a comment. Note that #{ is the start of a dictionary, therefore that starts a comment. Note that #{ is the start of a dictionary, therefore
it cannot start a comment. it cannot start a comment.
Since Vim9 script allows for line breaks in many places, the double quoted
comment also cannot be used at the start of a line after an expression. To
avoid confusion it is best to only use # comments.
Vim9 functions ~ Vim9 functions ~
@@ -400,6 +404,7 @@ The boolean operators "||" and "&&" do not change the value: >
0 || '' == '' 0 || '' == ''
8 && 2 == 2 8 && 2 == 2
0 && 2 == 0 0 && 2 == 0
2 && 0 == 0
[] && 2 == [] [] && 2 == []
When using `..` for string concatenation the arguments are always converted to When using `..` for string concatenation the arguments are always converted to
@@ -418,13 +423,15 @@ be made. Here is a summary of what might be unexpected.
Ex command ranges need to be prefixed with a colon. > Ex command ranges need to be prefixed with a colon. >
-> " legacy Vim: shifts the previous line to the right -> " legacy Vim: shifts the previous line to the right
->func() " Vim9: method call ->func() " Vim9: method call in continuation line
:-> " Vim9: shifts the previous line to the right :-> " Vim9: shifts the previous line to the right
%s/a/b " legacy Vim: substitute on all lines %s/a/b " legacy Vim: substitute on all lines
x = alongname x = alongname
% another " Vim9: line continuation without a backslash % another " Vim9: line continuation without a backslash
:%s/a/b " Vim9: substitute on all lines :%s/a/b " Vim9: substitute on all lines
'text'->func() " Vim9: method call
:'t " legacy Vim: jump to mark m
Functions defined with `:def` compile the whole function. Legacy functions Functions defined with `:def` compile the whole function. Legacy functions
can bail out, and the following lines are not parsed: > can bail out, and the following lines are not parsed: >

View File

@@ -1649,6 +1649,16 @@ current_tab_nr(tabpage_T *tab)
return nr; return nr;
} }
int
comment_start(char_u *p, int starts_with_colon UNUSED)
{
#ifdef FEAT_EVAL
if (in_vim9script())
return p[0] == '#' && p[1] != '{' && !starts_with_colon;
#endif
return *p == '"';
}
# define CURRENT_WIN_NR current_win_nr(curwin) # define CURRENT_WIN_NR current_win_nr(curwin)
# define LAST_WIN_NR current_win_nr(NULL) # define LAST_WIN_NR current_win_nr(NULL)
# define CURRENT_TAB_NR current_tab_nr(curtab) # define CURRENT_TAB_NR current_tab_nr(curtab)
@@ -1886,11 +1896,7 @@ do_one_cmd(
* If we got a line, but no command, then go to the line. * If we got a line, but no command, then go to the line.
* If we find a '|' or '\n' we set ea.nextcmd. * If we find a '|' or '\n' we set ea.nextcmd.
*/ */
if (*ea.cmd == NUL || *ea.cmd == '"' if (*ea.cmd == NUL || comment_start(ea.cmd, starts_with_colon)
#ifdef FEAT_EVAL
|| (*ea.cmd == '#' && ea.cmd[1] != '{'
&& !starts_with_colon && vim9script)
#endif
|| (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
{ {
/* /*
@@ -2225,7 +2231,7 @@ do_one_cmd(
ea.do_ecmd_cmd = getargcmd(&ea.arg); ea.do_ecmd_cmd = getargcmd(&ea.arg);
/* /*
* Check for '|' to separate commands and '"' to start comments. * Check for '|' to separate commands and '"' or '#' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd". * Don't do this for ":read !cmd" and ":write !cmd".
*/ */
if ((ea.argt & EX_TRLBAR) && !ea.usefilter) if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
@@ -2660,6 +2666,7 @@ doend:
parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only) parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only)
{ {
char_u *p; char_u *p;
int starts_with_colon = FALSE;
CLEAR_FIELD(cmdmod); CLEAR_FIELD(cmdmod);
eap->verbose_save = -1; eap->verbose_save = -1;
@@ -2669,7 +2676,11 @@ parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only)
for (;;) for (;;)
{ {
while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':') while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':')
{
if (*eap->cmd == ':')
starts_with_colon = TRUE;
++eap->cmd; ++eap->cmd;
}
// in ex mode, an empty line works like :+ // in ex mode, an empty line works like :+
if (*eap->cmd == NUL && exmode_active if (*eap->cmd == NUL && exmode_active
@@ -2683,7 +2694,7 @@ parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only)
} }
// ignore comment and empty lines // ignore comment and empty lines
if (*eap->cmd == '"') if (comment_start(eap->cmd, starts_with_colon))
return FAIL; return FAIL;
if (*eap->cmd == NUL) if (*eap->cmd == NUL)
{ {
@@ -4521,14 +4532,20 @@ separate_nextcmd(exarg_T *eap)
// Check for '"': start of comment or '|': next command // Check for '"': start of comment or '|': next command
// :@" and :*" do not start a comment! // :@" and :*" do not start a comment!
// :redir @" doesn't either. // :redir @" doesn't either.
else if ((*p == '"' && !(eap->argt & EX_NOTRLCOM) else if ((*p == '"'
#ifdef FEAT_EVAL
&& !in_vim9script()
#endif
&& !(eap->argt & EX_NOTRLCOM)
&& ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star) && ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star)
|| p != eap->arg) || p != eap->arg)
&& (eap->cmdidx != CMD_redir && (eap->cmdidx != CMD_redir
|| p != eap->arg + 1 || p[-1] != '@')) || p != eap->arg + 1 || p[-1] != '@'))
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
|| (*p == '#' && in_vim9script() || (*p == '#'
&& p[1] != '{' && p > eap->cmd && VIM_ISWHITE(p[-1])) && in_vim9script()
&& p[1] != '{'
&& p > eap->cmd && VIM_ISWHITE(p[-1]))
#endif #endif
|| *p == '|' || *p == '\n') || *p == '|' || *p == '\n')
{ {
@@ -4867,11 +4884,13 @@ ex_blast(exarg_T *eap)
int int
ends_excmd(int c) ends_excmd(int c)
{ {
int comment_char = '"';
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
if (c == '#') if (in_vim9script())
return in_vim9script(); comment_char = '#';
#endif #endif
return (c == NUL || c == '|' || c == '"' || c == '\n'); return (c == NUL || c == '|' || c == comment_char || c == '\n');
} }
/* /*
@@ -4883,11 +4902,14 @@ ends_excmd2(char_u *cmd_start UNUSED, char_u *cmd)
{ {
int c = *cmd; int c = *cmd;
if (c == NUL || c == '|' || c == '\n')
return TRUE;
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
if (c == '#' && cmd[1] != '{' && (cmd == cmd_start || VIM_ISWHITE(cmd[-1]))) if (in_vim9script())
return in_vim9script(); return c == '#' && cmd[1] != '{'
&& (cmd == cmd_start || VIM_ISWHITE(cmd[-1]));
#endif #endif
return (c == NUL || c == '|' || c == '"' || c == '\n'); return c == '"';
} }
#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \ #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \
@@ -7029,7 +7051,12 @@ ex_wincmd(exarg_T *eap)
eap->nextcmd = check_nextcmd(p); eap->nextcmd = check_nextcmd(p);
p = skipwhite(p); p = skipwhite(p);
if (*p != NUL && *p != '"' && eap->nextcmd == NULL) if (*p != NUL && *p != (
#ifdef FEAT_EVAL
in_vim9script() ? '#' :
#endif
'"')
&& eap->nextcmd == NULL)
emsg(_(e_invarg)); emsg(_(e_invarg));
else if (!eap->skip) else if (!eap->skip)
{ {

View File

@@ -5,6 +5,7 @@ int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int, int), void
int getline_equal(char_u *(*fgetline)(int, void *, int, int), void *cookie, char_u *(*func)(int, void *, int, int)); int getline_equal(char_u *(*fgetline)(int, void *, int, int), void *cookie, char_u *(*func)(int, void *, int, int));
void *getline_cookie(char_u *(*fgetline)(int, void *, int, int), void *cookie); void *getline_cookie(char_u *(*fgetline)(int, void *, int, int), void *cookie);
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, int), void *cookie); char_u *getline_peek(char_u *(*fgetline)(int, void *, int, int), void *cookie);
int comment_start(char_u *p, int starts_with_colon);
int parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only); int parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only);
void undo_cmdmod(exarg_T *eap, int save_msg_scroll); void undo_cmdmod(exarg_T *eap, int save_msg_scroll);
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent); int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);

View File

@@ -463,7 +463,7 @@ def Test_disassemble_update_instr()
'\d RETURN', '\d RETURN',
res) res)
" Calling the function will change UCALL into the faster DCALL # Calling the function will change UCALL into the faster DCALL
assert_equal('yes', FuncWithForwardCall()) assert_equal('yes', FuncWithForwardCall())
res = execute('disass s:FuncWithForwardCall') res = execute('disass s:FuncWithForwardCall')
@@ -1073,7 +1073,7 @@ def Test_disassemble_compare()
let nr = 1 let nr = 1
for case in cases for case in cases
" declare local variables to get a non-constant with the right type # declare local variables to get a non-constant with the right type
writefile(['def TestCase' .. nr .. '()', writefile(['def TestCase' .. nr .. '()',
' let isFalse = false', ' let isFalse = false',
' let isNull = v:null', ' let isNull = v:null',
@@ -1121,7 +1121,7 @@ def Test_disassemble_compare_const()
source Xdisassemble source Xdisassemble
let instr = execute('disassemble TestCase' .. nr) let instr = execute('disassemble TestCase' .. nr)
if case[1] if case[1]
" condition true, "echo 42" executed # condition true, "echo 42" executed
assert_match('TestCase' .. nr .. '.*' .. assert_match('TestCase' .. nr .. '.*' ..
'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*' .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*' ..
'\d PUSHNR 42.*' .. '\d PUSHNR 42.*' ..
@@ -1130,7 +1130,7 @@ def Test_disassemble_compare_const()
'\d RETURN.*', '\d RETURN.*',
instr) instr)
else else
" condition false, function just returns # condition false, function just returns
assert_match('TestCase' .. nr .. '.*' .. assert_match('TestCase' .. nr .. '.*' ..
'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '[ \n]*' .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '[ \n]*' ..
'echo 42[ \n]*' .. 'echo 42[ \n]*' ..
@@ -1245,7 +1245,7 @@ def Test_vim9script_forward_func()
writefile(lines, 'Xdisassemble') writefile(lines, 'Xdisassemble')
source Xdisassemble source Xdisassemble
" check that the first function calls the second with DCALL # check that the first function calls the second with DCALL
assert_match('\<SNR>\d*_FuncOne\_s*' .. assert_match('\<SNR>\d*_FuncOne\_s*' ..
'return FuncTwo()\_s*' .. 'return FuncTwo()\_s*' ..
'\d DCALL <SNR>\d\+_FuncTwo(argc 0)\_s*' .. '\d DCALL <SNR>\d\+_FuncTwo(argc 0)\_s*' ..

View File

@@ -46,7 +46,7 @@ def Test_expr1()
enddef enddef
def Test_expr1_vimscript() def Test_expr1_vimscript()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
let var = 1 let var = 1
@@ -127,7 +127,7 @@ def Test_expr2()
enddef enddef
def Test_expr2_vimscript() def Test_expr2_vimscript()
" check line continuation # check line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
let var = 0 let var = 0
@@ -154,7 +154,7 @@ def Test_expr2_vimscript()
END END
CheckScriptSuccess(lines) CheckScriptSuccess(lines)
" check keeping the value # check keeping the value
lines =<< trim END lines =<< trim END
vim9script vim9script
assert_equal(2, 2 || 0) assert_equal(2, 2 || 0)
@@ -231,7 +231,7 @@ def Test_expr3()
enddef enddef
def Test_expr3_vimscript() def Test_expr3_vimscript()
" check line continuation # check line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
let var = 0 let var = 0
@@ -258,7 +258,7 @@ def Test_expr3_vimscript()
END END
CheckScriptSuccess(lines) CheckScriptSuccess(lines)
" check keeping the value # check keeping the value
lines =<< trim END lines =<< trim END
vim9script vim9script
assert_equal(0, 2 && 0) assert_equal(0, 2 && 0)
@@ -625,7 +625,7 @@ def RetVoid()
enddef enddef
def Test_expr4_vimscript() def Test_expr4_vimscript()
" check line continuation # check line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
let var = 0 let var = 0
@@ -668,7 +668,7 @@ def Test_expr4_vimscript()
END END
CheckScriptSuccess(lines) CheckScriptSuccess(lines)
" spot check mismatching types # spot check mismatching types
lines =<< trim END lines =<< trim END
vim9script vim9script
echo '' == 0 echo '' == 0
@@ -791,7 +791,7 @@ def Test_expr5()
enddef enddef
def Test_expr5_vim9script() def Test_expr5_vim9script()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
let var = 11 let var = 11
@@ -902,7 +902,7 @@ def Test_expr6()
enddef enddef
def Test_expr6_vim9script() def Test_expr6_vim9script()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
let var = 11 let var = 11
@@ -1024,7 +1024,7 @@ let $TESTVAR = 'testvar'
" test low level expression " test low level expression
def Test_expr7_number() def Test_expr7_number()
" number constant # number constant
assert_equal(0, 0) assert_equal(0, 0)
assert_equal(654, 0654) assert_equal(654, 0654)
@@ -1034,7 +1034,7 @@ def Test_expr7_number()
enddef enddef
def Test_expr7_float() def Test_expr7_float()
" float constant # float constant
if !has('float') if !has('float')
MissingFeature 'float' MissingFeature 'float'
else else
@@ -1046,7 +1046,7 @@ def Test_expr7_float()
enddef enddef
def Test_expr7_blob() def Test_expr7_blob()
" blob constant # blob constant
assert_equal(g:blob_empty, 0z) assert_equal(g:blob_empty, 0z)
assert_equal(g:blob_one, 0z01) assert_equal(g:blob_one, 0z01)
assert_equal(g:blob_long, 0z0102.0304) assert_equal(g:blob_long, 0z0102.0304)
@@ -1055,7 +1055,7 @@ def Test_expr7_blob()
enddef enddef
def Test_expr7_string() def Test_expr7_string()
" string constant # string constant
assert_equal(g:string_empty, '') assert_equal(g:string_empty, '')
assert_equal(g:string_empty, "") assert_equal(g:string_empty, "")
assert_equal(g:string_short, 'x') assert_equal(g:string_short, 'x')
@@ -1077,7 +1077,7 @@ def Test_expr7_vimvar()
enddef enddef
def Test_expr7_special() def Test_expr7_special()
" special constant # special constant
assert_equal(g:special_true, true) assert_equal(g:special_true, true)
assert_equal(g:special_false, false) assert_equal(g:special_false, false)
assert_equal(g:special_true, v:true) assert_equal(g:special_true, v:true)
@@ -1106,7 +1106,7 @@ def Test_expr7_special_vim9script()
enddef enddef
def Test_expr7_list() def Test_expr7_list()
" list # list
assert_equal(g:list_empty, []) assert_equal(g:list_empty, [])
assert_equal(g:list_empty, [ ]) assert_equal(g:list_empty, [ ])
assert_equal(g:list_mixed, [1, 'b', false,]) assert_equal(g:list_mixed, [1, 'b', false,])
@@ -1152,7 +1152,7 @@ def Test_expr7_lambda()
assert_equal('result', La()) assert_equal('result', La())
assert_equal([1, 3, 5], [1, 2, 3]->map({key, val -> key + val})) assert_equal([1, 3, 5], [1, 2, 3]->map({key, val -> key + val}))
" line continuation inside lambda with "cond ? expr : expr" works # line continuation inside lambda with "cond ? expr : expr" works
let ll = range(3) let ll = range(3)
map(ll, {k, v -> v % 2 ? { map(ll, {k, v -> v % 2 ? {
'111': 111 } : {} '111': 111 } : {}
@@ -1189,7 +1189,7 @@ def Test_expr7_lambda_vim9script()
enddef enddef
def Test_expr7_dict() def Test_expr7_dict()
" dictionary # dictionary
assert_equal(g:dict_empty, {}) assert_equal(g:dict_empty, {})
assert_equal(g:dict_empty, { }) assert_equal(g:dict_empty, { })
assert_equal(g:dict_one, {'one': 1}) assert_equal(g:dict_one, {'one': 1})
@@ -1316,7 +1316,7 @@ def Test_expr_member_vim9script()
enddef enddef
def Test_expr7_option() def Test_expr7_option()
" option # option
set ts=11 set ts=11
assert_equal(11, &ts) assert_equal(11, &ts)
&ts = 9 &ts = 9
@@ -1330,7 +1330,7 @@ def Test_expr7_option()
enddef enddef
def Test_expr7_environment() def Test_expr7_environment()
" environment variable # environment variable
assert_equal('testvar', $TESTVAR) assert_equal('testvar', $TESTVAR)
assert_equal('', $ASDF_ASD_XXX) assert_equal('', $ASDF_ASD_XXX)
@@ -1343,7 +1343,7 @@ def Test_expr7_register()
enddef enddef
def Test_expr7_parens() def Test_expr7_parens()
" (expr) # (expr)
assert_equal(4, (6 * 4) / 6) assert_equal(4, (6 * 4) / 6)
assert_equal(0, 6 * ( 4 / 6 )) assert_equal(0, 6 * ( 4 / 6 ))
@@ -1474,7 +1474,7 @@ func CallMe2(one, two)
endfunc endfunc
def Test_expr7_trailing() def Test_expr7_trailing()
" user function call # user function call
assert_equal(123, g:CallMe(123)) assert_equal(123, g:CallMe(123))
assert_equal(123, g:CallMe( 123)) assert_equal(123, g:CallMe( 123))
assert_equal(123, g:CallMe(123 )) assert_equal(123, g:CallMe(123 ))
@@ -1482,26 +1482,26 @@ def Test_expr7_trailing()
assert_equal('yesno', g:CallMe2( 'yes', 'no' )) assert_equal('yesno', g:CallMe2( 'yes', 'no' ))
assert_equal('nothing', g:CallMe('nothing')) assert_equal('nothing', g:CallMe('nothing'))
" partial call # partial call
let Part = function('g:CallMe') let Part = function('g:CallMe')
assert_equal('yes', Part('yes')) assert_equal('yes', Part('yes'))
" funcref call, using list index # funcref call, using list index
let l = [] let l = []
g:Funcrefs[0](l, 2) g:Funcrefs[0](l, 2)
assert_equal([2], l) assert_equal([2], l)
" method call # method call
l = [2, 5, 6] l = [2, 5, 6]
l->map({k, v -> k + v}) l->map({k, v -> k + v})
assert_equal([2, 6, 8], l) assert_equal([2, 6, 8], l)
" lambda method call # lambda method call
l = [2, 5] l = [2, 5]
l->{l -> add(l, 8)}() l->{l -> add(l, 8)}()
assert_equal([2, 5, 8], l) assert_equal([2, 5, 8], l)
" dict member # dict member
let d = #{key: 123} let d = #{key: 123}
assert_equal(123, d.key) assert_equal(123, d.key)
enddef enddef

View File

@@ -80,7 +80,7 @@ def Test_call_ufunc_count()
Increment() Increment()
Increment() Increment()
Increment() Increment()
" works with and without :call # works with and without :call
assert_equal(4, g:counter) assert_equal(4, g:counter)
call assert_equal(4, g:counter) call assert_equal(4, g:counter)
unlet g:counter unlet g:counter
@@ -236,7 +236,7 @@ def ListArg(arg: list<string>)
enddef enddef
def Test_assign_to_argument() def Test_assign_to_argument()
" works for dict and list # works for dict and list
let d: dict<string> = {} let d: dict<string> = {}
DictArg(d) DictArg(d)
assert_equal('value', d['key']) assert_equal('value', d['key'])
@@ -266,19 +266,19 @@ let SomeFunc = function('len')
let NotAFunc = 'text' let NotAFunc = 'text'
def CombineFuncrefTypes() def CombineFuncrefTypes()
" same arguments, different return type # same arguments, different return type
let Ref1: func(bool): string let Ref1: func(bool): string
let Ref2: func(bool): number let Ref2: func(bool): number
let Ref3: func(bool): any let Ref3: func(bool): any
Ref3 = g:cond ? Ref1 : Ref2 Ref3 = g:cond ? Ref1 : Ref2
" different number of arguments # different number of arguments
let Refa1: func(bool): number let Refa1: func(bool): number
let Refa2: func(bool, number): number let Refa2: func(bool, number): number
let Refa3: func: number let Refa3: func: number
Refa3 = g:cond ? Refa1 : Refa2 Refa3 = g:cond ? Refa1 : Refa2
" different argument types # different argument types
let Refb1: func(bool, string): number let Refb1: func(bool, string): number
let Refb2: func(string, number): number let Refb2: func(string, number): number
let Refb3: func(any, any): number let Refb3: func(any, any): number
@@ -294,7 +294,7 @@ def DefinedEvenLater(arg: string): string
enddef enddef
def Test_error_in_nested_function() def Test_error_in_nested_function()
" Error in called function requires unwinding the call stack. # Error in called function requires unwinding the call stack.
assert_fails('call FuncWithForwardCall()', 'E1096') assert_fails('call FuncWithForwardCall()', 'E1096')
enddef enddef

View File

@@ -113,7 +113,7 @@ def Test_vim9_single_char_vars()
let lines =<< trim END let lines =<< trim END
vim9script vim9script
" single character variable declarations work # single character variable declarations work
let a: string let a: string
let b: number let b: number
let l: list<any> let l: list<any>
@@ -122,7 +122,7 @@ def Test_vim9_single_char_vars()
let v: number let v: number
let w: number let w: number
" script-local variables can be used without s: prefix # script-local variables can be used without s: prefix
a = 'script-a' a = 'script-a'
b = 111 b = 111
l = [1, 2, 3] l = [1, 2, 3]
@@ -175,7 +175,7 @@ def Test_assignment_dict()
let dict4: dict<any> = #{one: 1, two: '2'} let dict4: dict<any> = #{one: 1, two: '2'}
let dict5: dict<blob> = #{one: 0z01, two: 0z02} let dict5: dict<blob> = #{one: 0z01, two: 0z02}
" overwrite # overwrite
dict3['key'] = 'another' dict3['key'] = 'another'
call CheckDefExecFailure(['let dd = {}', 'dd[""] = 6'], 'E713:') call CheckDefExecFailure(['let dd = {}', 'dd[""] = 6'], 'E713:')
@@ -185,8 +185,8 @@ def Test_assignment_dict()
enddef enddef
def Test_assignment_local() def Test_assignment_local()
" Test in a separated file in order not to the current buffer/window/tab is # Test in a separated file in order not to the current buffer/window/tab is
" changed. # changed.
let script_lines: list<string> =<< trim END let script_lines: list<string> =<< trim END
let b:existing = 'yes' let b:existing = 'yes'
let w:existing = 'yes' let w:existing = 'yes'
@@ -259,7 +259,7 @@ def Test_assignment_default()
assert_equal(test_null_channel(), thechannel) assert_equal(test_null_channel(), thechannel)
if has('unix') && executable('cat') if has('unix') && executable('cat')
" check with non-null job and channel, types must match # check with non-null job and channel, types must match
thejob = job_start("cat ", #{}) thejob = job_start("cat ", #{})
thechannel = job_getchannel(thejob) thechannel = job_getchannel(thejob)
job_stop(thejob, 'kill') job_stop(thejob, 'kill')
@@ -394,7 +394,7 @@ def Test_unlet()
enddef enddef
def Test_delfunction() def Test_delfunction()
" Check function is defined in script namespace # Check function is defined in script namespace
CheckScriptSuccess([ CheckScriptSuccess([
'vim9script', 'vim9script',
'func CheckMe()', 'func CheckMe()',
@@ -403,7 +403,7 @@ def Test_delfunction()
'assert_equal(123, s:CheckMe())', 'assert_equal(123, s:CheckMe())',
]) ])
" Check function in script namespace cannot be deleted # Check function in script namespace cannot be deleted
CheckScriptFailure([ CheckScriptFailure([
'vim9script', 'vim9script',
'func DeleteMe1()', 'func DeleteMe1()',
@@ -586,7 +586,7 @@ def Test_try_catch_fails()
enddef enddef
def Test_throw_vimscript() def Test_throw_vimscript()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
try try
@@ -600,7 +600,7 @@ def Test_throw_vimscript()
enddef enddef
def Test_cexpr_vimscript() def Test_cexpr_vimscript()
" only checks line continuation # only checks line continuation
set errorformat=File\ %f\ line\ %l set errorformat=File\ %f\ line\ %l
let lines =<< trim END let lines =<< trim END
vim9script vim9script
@@ -727,7 +727,7 @@ def Test_vim9_import_export()
END END
writefile(import_in_def_lines, 'Ximport2.vim') writefile(import_in_def_lines, 'Ximport2.vim')
source Ximport2.vim source Ximport2.vim
" TODO: this should be 9879 # TODO: this should be 9879
assert_equal(9876, g:imported) assert_equal(9876, g:imported)
assert_equal(9883, g:imported_added) assert_equal(9883, g:imported_added)
unlet g:imported unlet g:imported
@@ -802,7 +802,7 @@ def Test_vim9_import_export()
writefile(import_star_lines, 'Ximport.vim') writefile(import_star_lines, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1045:') assert_fails('source Ximport.vim', 'E1045:')
" try to import something that exists but is not exported # try to import something that exists but is not exported
let import_not_exported_lines =<< trim END let import_not_exported_lines =<< trim END
vim9script vim9script
import name from './Xexport.vim' import name from './Xexport.vim'
@@ -810,7 +810,7 @@ def Test_vim9_import_export()
writefile(import_not_exported_lines, 'Ximport.vim') writefile(import_not_exported_lines, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1049:') assert_fails('source Ximport.vim', 'E1049:')
" try to import something that is already defined # try to import something that is already defined
let import_already_defined =<< trim END let import_already_defined =<< trim END
vim9script vim9script
let exported = 'something' let exported = 'something'
@@ -819,7 +819,7 @@ def Test_vim9_import_export()
writefile(import_already_defined, 'Ximport.vim') writefile(import_already_defined, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1073:') assert_fails('source Ximport.vim', 'E1073:')
" try to import something that is already defined # try to import something that is already defined
import_already_defined =<< trim END import_already_defined =<< trim END
vim9script vim9script
let exported = 'something' let exported = 'something'
@@ -828,7 +828,7 @@ def Test_vim9_import_export()
writefile(import_already_defined, 'Ximport.vim') writefile(import_already_defined, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1073:') assert_fails('source Ximport.vim', 'E1073:')
" try to import something that is already defined # try to import something that is already defined
import_already_defined =<< trim END import_already_defined =<< trim END
vim9script vim9script
let exported = 'something' let exported = 'something'
@@ -837,7 +837,7 @@ def Test_vim9_import_export()
writefile(import_already_defined, 'Ximport.vim') writefile(import_already_defined, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1073:') assert_fails('source Ximport.vim', 'E1073:')
" import a very long name, requires making a copy # import a very long name, requires making a copy
let import_long_name_lines =<< trim END let import_long_name_lines =<< trim END
vim9script vim9script
import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
@@ -877,7 +877,7 @@ def Test_vim9_import_export()
delete('Ximport3.vim') delete('Ximport3.vim')
delete('Xexport.vim') delete('Xexport.vim')
" Check that in a Vim9 script 'cpo' is set to the Vim default. # Check that in a Vim9 script 'cpo' is set to the Vim default.
set cpo&vi set cpo&vi
let cpo_before = &cpo let cpo_before = &cpo
let lines =<< trim END let lines =<< trim END
@@ -962,12 +962,12 @@ def Test_vim9script_reload_import()
writefile(testlines, 'Ximport.vim') writefile(testlines, 'Ximport.vim')
source Ximport.vim source Ximport.vim
" Test that when not using "morelines" GetValtwo() and valtwo are still # Test that when not using "morelines" GetValtwo() and valtwo are still
" defined, because import doesn't reload a script. # defined, because import doesn't reload a script.
writefile(lines, 'Xreload.vim') writefile(lines, 'Xreload.vim')
source Ximport.vim source Ximport.vim
" cannot declare a var twice # cannot declare a var twice
lines =<< trim END lines =<< trim END
vim9script vim9script
let valone = 1234 let valone = 1234
@@ -1185,7 +1185,7 @@ def Test_import_compile_error()
try try
source Ximport.vim source Ximport.vim
catch /E1001/ catch /E1001/
" Error should be fore the Xexported.vim file. # Error should be fore the Xexported.vim file.
assert_match('E1001: variable not found: notDefined', v:exception) assert_match('E1001: variable not found: notDefined', v:exception)
assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint)
endtry endtry
@@ -1195,7 +1195,7 @@ def Test_import_compile_error()
enddef enddef
def Test_fixed_size_list() def Test_fixed_size_list()
" will be allocated as one piece of memory, check that changes work # will be allocated as one piece of memory, check that changes work
let l = [1, 2, 3, 4] let l = [1, 2, 3, 4]
l->remove(0) l->remove(0)
l->add(5) l->add(5)
@@ -1357,9 +1357,9 @@ def RunNested(i: number): number
let x: number = 0 let x: number = 0
if i % 2 if i % 2
if 1 if 1
" comment # comment
else else
" comment # comment
endif endif
x += 1 x += 1
else else
@@ -1401,7 +1401,7 @@ def Test_execute_cmd()
enddef enddef
def Test_execute_cmd_vimscript() def Test_execute_cmd_vimscript()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
execute 'g:someVar' execute 'g:someVar'
@@ -1441,7 +1441,7 @@ def Test_echomsg_cmd()
enddef enddef
def Test_echomsg_cmd_vimscript() def Test_echomsg_cmd_vimscript()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
echomsg 'here' echomsg 'here'
@@ -1461,7 +1461,7 @@ def Test_echoerr_cmd()
enddef enddef
def Test_echoerr_cmd_vimscript() def Test_echoerr_cmd_vimscript()
" only checks line continuation # only checks line continuation
let lines =<< trim END let lines =<< trim END
vim9script vim9script
try try
@@ -1569,7 +1569,7 @@ def Test_automatic_line_continuation()
'one', 'one',
'two', 'two',
'three', 'three',
] " comment ] # comment
assert_equal(['one', 'two', 'three'], mylist) assert_equal(['one', 'two', 'three'], mylist)
let mydict = { let mydict = {
@@ -1577,7 +1577,7 @@ def Test_automatic_line_continuation()
'two': 2, 'two': 2,
'three': 'three':
3, 3,
} " comment } # comment
assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict) assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict)
mydict = #{ mydict = #{
one: 1, # comment one: 1, # comment
@@ -1754,8 +1754,8 @@ def Test_vim9_comment()
'hi clear This # comment', 'hi clear This # comment',
'hi clear # comment', 'hi clear # comment',
]) ])
" not tested, because it doesn't give an error but a warning: # not tested, because it doesn't give an error but a warning:
" hi clear This# comment', # hi clear This# comment',
CheckScriptFailure([ CheckScriptFailure([
'vim9script', 'vim9script',
'hi clear# comment', 'hi clear# comment',
@@ -2091,19 +2091,19 @@ def Test_vim9_comment_not_compiled()
'bwipe!', 'bwipe!',
]) ])
" CheckScriptFailure([ CheckScriptFailure([
" 'vim9script', 'vim9script',
" 'new' 'new'
" 'call setline(1, ["# define pat", "last"])', 'call setline(1, ["# define pat", "last"])',
" ':$', ':$',
" 'dsearch /pat/#comment', 'dsearch /pat/#comment',
" 'bwipe!', 'bwipe!',
" ], 'E488:') ], 'E488:')
"
" CheckScriptFailure([ CheckScriptFailure([
" 'vim9script', 'vim9script',
" 'func! SomeFunc()', 'func! SomeFunc()',
" ], 'E477:') ], 'E477:')
enddef enddef
def Test_finish() def Test_finish()
@@ -2135,12 +2135,12 @@ def Test_let_func_call()
return 'this' return 'this'
endfunc endfunc
let val: string = GetValue() let val: string = GetValue()
" env var is always a string # env var is always a string
let env = $TERM let env = $TERM
END END
writefile(lines, 'Xfinished') writefile(lines, 'Xfinished')
source Xfinished source Xfinished
" GetValue() is not called during discovery phase # GetValue() is not called during discovery phase
assert_equal(1, g:count) assert_equal(1, g:count)
unlet g:count unlet g:count
@@ -2169,7 +2169,7 @@ def Test_let_declaration()
g:var_uninit = var g:var_uninit = var
var = 'text' var = 'text'
g:var_test = var g:var_test = var
" prefixing s: is optional # prefixing s: is optional
s:var = 'prefixed' s:var = 'prefixed'
g:var_prefixed = s:var g:var_prefixed = s:var
@@ -2281,7 +2281,7 @@ def Test_source_vim9_from_legacy()
source Xlegacy_script.vim source Xlegacy_script.vim
assert_equal('global', g:global) assert_equal('global', g:global)
" unlet g:global unlet g:global
delete('Xlegacy_script.vim') delete('Xlegacy_script.vim')
delete('Xvim9_script.vim') delete('Xvim9_script.vim')
@@ -2301,7 +2301,7 @@ def Test_substitute_cmd()
assert_equal('otherthing', getline(1)) assert_equal('otherthing', getline(1))
bwipe! bwipe!
" also when the context is Vim9 script # also when the context is Vim9 script
let lines =<< trim END let lines =<< trim END
vim9script vim9script
new new

View File

@@ -754,6 +754,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 */
/**/
1227,
/**/ /**/
1226, 1226,
/**/ /**/

View File

@@ -2420,7 +2420,7 @@ free_imported(cctx_T *cctx)
* Return TRUE if "p" points at a "#" but not at "#{". * Return TRUE if "p" points at a "#" but not at "#{".
*/ */
static int static int
comment_start(char_u *p) vim9_comment_start(char_u *p)
{ {
return p[0] == '#' && p[1] != '{'; return p[0] == '#' && p[1] != '{';
} }
@@ -2443,7 +2443,7 @@ peek_next_line_from_context(cctx_T *cctx)
if (line == NULL) if (line == NULL)
break; break;
p = skipwhite(line); p = skipwhite(line);
if (*p != NUL && !comment_start(p)) if (*p != NUL && !vim9_comment_start(p))
return p; return p;
} }
return NULL; return NULL;
@@ -2461,7 +2461,7 @@ may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
char_u *p = skipwhite(arg); char_u *p = skipwhite(arg);
*nextp = NULL; *nextp = NULL;
if (*p == NUL || (VIM_ISWHITE(*arg) && comment_start(p))) if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
{ {
*nextp = peek_next_line_from_context(cctx); *nextp = peek_next_line_from_context(cctx);
if (*nextp != NULL) if (*nextp != NULL)
@@ -2492,7 +2492,7 @@ next_line_from_context(cctx_T *cctx, int skip_comment)
cctx->ctx_line_start = line; cctx->ctx_line_start = line;
SOURCING_LNUM = cctx->ctx_lnum + 1; SOURCING_LNUM = cctx->ctx_lnum + 1;
} while (line == NULL || *skipwhite(line) == NUL } while (line == NULL || *skipwhite(line) == NUL
|| (skip_comment && comment_start(skipwhite(line)))); || (skip_comment && vim9_comment_start(skipwhite(line))));
return line; return line;
} }
@@ -2504,7 +2504,7 @@ next_line_from_context(cctx_T *cctx, int skip_comment)
static int static int
may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx) may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
{ {
if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg))) if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
{ {
char_u *next = next_line_from_context(cctx, TRUE); char_u *next = next_line_from_context(cctx, TRUE);
@@ -3100,7 +3100,7 @@ compile_list(char_u **arg, cctx_T *cctx)
{ {
++p; ++p;
// Allow for following comment, after at least one space. // Allow for following comment, after at least one space.
if (VIM_ISWHITE(*p) && *skipwhite(p) == '"') if (VIM_ISWHITE(*p) && *skipwhite(p) == '#')
p += STRLEN(p); p += STRLEN(p);
break; break;
} }
@@ -3157,6 +3157,8 @@ compile_lambda(char_u **arg, cctx_T *cctx)
if (ufunc->uf_def_status == UF_COMPILED) if (ufunc->uf_def_status == UF_COMPILED)
return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx); return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
func_ptr_unref(ufunc);
return FAIL; return FAIL;
} }
@@ -3201,6 +3203,8 @@ compile_lambda_call(char_u **arg, cctx_T *cctx)
// call the compiled function // call the compiled function
ret = generate_CALL(cctx, ufunc, argcount); ret = generate_CALL(cctx, ufunc, argcount);
if (ret == FAIL)
func_ptr_unref(ufunc);
return ret; return ret;
} }
@@ -3327,7 +3331,7 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
// Allow for following comment, after at least one space. // Allow for following comment, after at least one space.
p = skipwhite(*arg); p = skipwhite(*arg);
if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p))) if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
*arg += STRLEN(*arg); *arg += STRLEN(*arg);
dict_unref(d); dict_unref(d);
@@ -3618,7 +3622,7 @@ compile_subscript(
{ {
char_u *p = skipwhite(*arg); char_u *p = skipwhite(*arg);
if (*p == NUL || (VIM_ISWHITE(**arg) && comment_start(p))) if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
{ {
char_u *next = peek_next_line_from_context(cctx); char_u *next = peek_next_line_from_context(cctx);