Compare commits

...

15 Commits

Author SHA1 Message Date
Yegappan Lakshmanan
ad52f96a2d patch 8.2.3018: 'quickfixtextfunc' formatting is lost when switching buffers
Problem:    Formatting using quickfixtextfunc is lost when updating location
            lists for different buffers.  (Yorick Peterse)
Solution:   Use the right window for the locaiton list. (Yegappan Lakshmanan,
            closes #8400, closes #8403)
2021-06-19 18:22:53 +02:00
Bram Moolenaar
59b50c3bee patch 8.2.3017: Vim9: debugger shows too many lines
Problem:    Vim9: debugger shows too many lines.
Solution:   Truncate at a comment, "enddef", etc. (closes #8392)
2021-06-17 22:27:48 +02:00
Bram Moolenaar
fae55a9cb0 patch 8.2.3016: confusing error when expression is followed by comma
Problem:    Confusing error when expression is followed by comma.
Solution:   Give a different error for trailing text. (closes #8395)
2021-06-17 22:08:30 +02:00
Bram Moolenaar
74f4a965bc patch 8.2.3015: Vim9: Assigning to @# requires a string
Problem:    Vim9: Assigning to @# requires a string. (Naohiro Ono)
Solution:   Accent a number or a string. (closes #8396)
2021-06-17 21:03:07 +02:00
Dominique Pelle
6e9695525e patch 8.2.3014: Coverity warns for freeing static string
Problem:    Coverity warns for freeing static string.
Solution:   Do not assign static string to pointer. (Dominique Pellé,
            closes #8397)
2021-06-17 13:53:41 +02:00
Bram Moolenaar
4cea536bdf patch 8.2.3013: Vim: when debugging only first line of command is displayed
Problem:    Vim: when debugging only the first line of a command using line
            continuation is displayed.
Solution:   Find the next command and concatenate lines until that one.
            (closes #8392)
2021-06-16 22:24:40 +02:00
Christian Brabandt
29f0dc3689 patch 8.2.3012: when 'rightleft' is set the line number is drawn reversed
Problem:    When 'rightleft' is set the line number is sometimes drawn
            reversed.
Solution:   Adjust how space is handled. (Christian Brabandt, closes #8389,
            closes #8391)
2021-06-16 19:28:34 +02:00
Bram Moolenaar
6bc30b05e6 patch 8.2.3011: Vim9: cannot get argument values during debugging
Problem:    Vim9: cannot get argument values during debugging.
Solution:   Lookup names in the list of arguments.  Put debug instruction
            halfway for command.
2021-06-16 19:19:55 +02:00
Yegappan Lakshmanan
41a7f82dea patch 8.2.3010: not enough testing for viminfo code
Problem:    Not enough testing for viminfo code.
Solution:   Add a few more tests. (Yegappan Lakshmanan, closes #8390)
2021-06-16 15:53:17 +02:00
Bram Moolenaar
b90ac5e96e patch 8.2.3009: startup test may hang
Problem:    Startup test may hang.
Solution:   Do not run the test in the GUI.
2021-06-16 10:59:36 +02:00
Bram Moolenaar
55b6b60b69 patch 8.2.3008: startup test may hang
Problem:    Startup test may hang.
Solution:   Add quit command in the script.
2021-06-15 23:05:59 +02:00
Bram Moolenaar
61a417b7c1 patch 8.2.3007: Vim9: test for void value fails
Problem:    Vim9: test for void value fails.
Solution:   Adjust expected error.  Do not make a copy of void.
2021-06-15 22:54:28 +02:00
Bram Moolenaar
a97c36310f patch 8.2.3006: crash when echoing a value very early
Problem:    Crash when echoing a value very early. (Naruhiko Nishino)
Solution:   Do not use a NUL to truncate the message, make a copy.
            (closes #8388)
2021-06-15 22:39:11 +02:00
Bram Moolenaar
f57b43c230 patch 8.2.3005: Vim9: using a void value does not give a proper error message
Problem:    Vim9: using a void value does not give a proper error message.
Solution:   Give a clear error message. (clodes #8387)
2021-06-15 22:13:27 +02:00
Bram Moolenaar
8ac681a280 patch 8.2.3004: Vim9: error for missing colon given while skipping
Problem:    Vim9: error for missing colon given while skipping.
Solution:   Do not give the error when skipping. (closes #8385)
2021-06-15 20:06:34 +02:00
27 changed files with 794 additions and 116 deletions

View File

@@ -1121,8 +1121,9 @@ win_line(
int t;
// like rl_mirror(), but keep the space at the end
p2 = skiptowhite(extra) - 1;
for (p1 = extra; p1 < p2; ++p1, --p2)
p2 = skipwhite(extra);
p2 = skiptowhite(p2) - 1;
for (p1 = skipwhite(extra); p1 < p2; ++p1, --p2)
{
t = *p1;
*p1 = *p2;

View File

@@ -2218,12 +2218,15 @@ eval0(
int did_emsg_before = did_emsg;
int called_emsg_before = called_emsg;
int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
int end_error = FALSE;
p = skipwhite(arg);
ret = eval1(&p, rettv, evalarg);
p = skipwhite(p);
if (ret == FAIL || !ends_excmd2(arg, p))
if (ret != FAIL)
end_error = !ends_excmd2(arg, p);
if (ret == FAIL || end_error)
{
if (ret != FAIL)
clear_tv(rettv);
@@ -2238,7 +2241,12 @@ eval0(
&& called_emsg == called_emsg_before
&& (flags & EVAL_CONSTANT) == 0
&& (!in_vim9script() || !vim9_bad_comment(p)))
semsg(_(e_invexpr2), arg);
{
if (end_error)
semsg(_(e_trailing_arg), p);
else
semsg(_(e_invexpr2), arg);
}
// Some of the expression may not have been consumed. Do not check for
// a next command to avoid more errors, unless "|" is following, which

View File

@@ -1844,7 +1844,7 @@ do_one_cmd(
// If a ':' before the range is missing, give a clearer error
// message.
if (ar > ea.cmd)
if (ar > ea.cmd && !ea.skip)
{
semsg(_(e_colon_required_before_range_str), ea.cmd);
goto doend;

View File

@@ -418,6 +418,9 @@ EXTERN type_T t_blob INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL);
// Special value used for @#.
EXTERN type_T t_number_or_string INIT6(VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_func_unknown INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_unknown, NULL);
EXTERN type_T t_func_void INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void, NULL);
EXTERN type_T t_func_any INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL);

View File

@@ -2751,19 +2751,21 @@ msg_puts_printf(char_u *str, int maxlen)
if (*p != NUL && !(silent_mode && p_verbose == 0))
{
int c = -1;
char_u *tofree = NULL;
if (maxlen > 0 && STRLEN(p) > (size_t)maxlen)
{
c = p[maxlen];
p[maxlen] = 0;
tofree = vim_strnsave(p, (size_t)maxlen);
p = tofree;
}
if (p != NULL)
{
if (info_message)
mch_msg((char *)p);
else
mch_errmsg((char *)p);
vim_free(tofree);
}
if (info_message)
mch_msg((char *)p);
else
mch_errmsg((char *)p);
if (c != -1)
p[maxlen] = c;
}
msg_didout = TRUE; // assume that line is not empty

View File

@@ -4473,7 +4473,17 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
int qf_winid = 0;
if (IS_LL_STACK(qi))
qf_winid = curwin->w_id;
{
if (curwin->w_llist == qi)
win = curwin;
else
{
win = qf_find_win_with_loclist(qi);
if (win == NULL)
return;
}
qf_winid = win->w_id;
}
if (old_last == NULL)
// set curwin/curbuf to buf and save a few things

View File

@@ -462,6 +462,9 @@ stuff_yank(int regname, char_u *p)
return OK;
}
/*
* Last executed register (@ command)
*/
static int execreg_lastc = NUL;
int

View File

@@ -885,19 +885,19 @@ func Test_Backtrace_DefFunction()
\ ':debug call GlobalFunction()',
\ ['cmd: call GlobalFunction()'])
call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
call RunDbgCmd(buf, 'echo some', ['some var'])
call RunDbgCmd(buf, 'backtrace', [
\ '\V>backtrace',
\ '\V->0 function GlobalFunction',
\ '\Vline 2: CallAFunction()',
\ '\Vline 2: CallAFunction()',
\ ],
\ #{match: 'pattern'})
call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
" Repeated line, because we fist are in the compiled function before the
" EXEC and then in do_cmdline() before the :source command.
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
@@ -937,12 +937,31 @@ func Test_debug_def_function()
let file =<< trim END
vim9script
def g:Func()
var n: number
def Closure(): number
return n + 3
enddef
n += Closure()
echo 'result: ' .. n
var n: number
def Closure(): number
return n + 3
enddef
n += Closure()
echo 'result: ' .. n
enddef
def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
echo text .. nr
for it in items
echo it
endfor
echo "done"
enddef
def g:FuncWithDict()
var d = {
a: 1,
b: 2,
}
# comment
def Inner()
eval 1
enddef
enddef
END
call writefile(file, 'Xtest.vim')
@@ -954,7 +973,37 @@ func Test_debug_def_function()
\ ['cmd: call Func()'])
call RunDbgCmd(buf, 'next', ['result: 3'])
call term_sendkeys(buf, "\r")
call RunDbgCmd(buf, 'cont')
call RunDbgCmd(buf,
\ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
\ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
call RunDbgCmd(buf, 'echo text', ['asdf'])
call RunDbgCmd(buf, 'echo nr', ['42'])
call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
call RunDbgCmd(buf, 'echo it', ['1'])
call RunDbgCmd(buf, 'step', ['line 3: echo it'])
call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
call RunDbgCmd(buf, 'echo it', ['2'])
call RunDbgCmd(buf, 'step', ['line 3: echo it'])
call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
call RunDbgCmd(buf, 'echo it', ['3'])
call RunDbgCmd(buf, 'step', ['line 3: echo it'])
call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
call RunDbgCmd(buf, 'cont')
call RunDbgCmd(buf,
\ ':debug call FuncWithDict()',
\ ['cmd: call FuncWithDict()'])
call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
call RunDbgCmd(buf, 'cont')
call StopVimInTerminal(buf)
call delete('Xtest.vim')
endfunc

View File

@@ -165,7 +165,7 @@ func Test_string_concat_scriptversion2()
call assert_fails('echo a . b', 'E15:')
call assert_fails('let a .= b', 'E985:')
call assert_fails('let vers = 1.2.3', 'E15:')
call assert_fails('let vers = 1.2.3', 'E488:')
if has('float')
let f = .5

View File

@@ -1,5 +1,7 @@
" Test for 'fileformat'
source shared.vim
" Test behavior of fileformat after bwipeout of last buffer
func Test_fileformat_after_bw()
bwipeout
@@ -308,4 +310,18 @@ func Test_fileformat_plusplus_read()
call assert_fails('e ++abc1 Xfile1', 'E474:')
endfunc
" When Vim starts up with an empty buffer the first item in 'fileformats' is
" used as the 'fileformat'.
func Test_fileformat_on_startup()
let after =<< trim END
call writefile([&fileformat], 'Xfile', 'a')
quit
END
call RunVim(["set ffs=dos,unix,mac"], after, '')
call RunVim(["set ffs=mac,dos,unix"], after, '')
call RunVim(["set ffs=unix,mac,dos"], after, '')
call assert_equal(['dos', 'mac', 'unix'], readfile('Xfile'))
call delete('Xfile')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -86,13 +86,13 @@ func Test_empty()
endfunc
func Test_test_void()
call assert_fails('echo 1 == test_void()', 'E685:')
call assert_fails('echo 1 == test_void()', 'E1031:')
if has('float')
call assert_fails('echo 1.0 == test_void()', 'E685:')
call assert_fails('echo 1.0 == test_void()', 'E1031:')
endif
call assert_fails('let x = json_encode(test_void())', 'E685:')
call assert_fails('let x = copy(test_void())', 'E685:')
call assert_fails('let x = copy([test_void()])', 'E685:')
call assert_fails('let x = copy([test_void()])', 'E1031:')
endfunc
func Test_len()

View File

@@ -314,6 +314,7 @@ func Test_let_errors()
let ch = test_null_channel()
call assert_fails('let ch += 1', 'E734:')
endif
call assert_fails('let name = "a" .. "b",', 'E488: Trailing characters: ,')
" This test works only when the language is English
if v:lang == "C" || v:lang =~ '^[Ee]n'

View File

@@ -298,4 +298,26 @@ func Test_relativenumber_colors()
call delete('XTest_relnr')
endfunc
" Test for displaying line numbers with 'rightleft'
func Test_number_rightleft()
CheckFeature rightleft
new
setlocal number
setlocal rightleft
call setline(1, range(1, 1000))
normal! 9Gzt
redraw!
call assert_match('^\s\+9 9$', Screenline(1))
normal! 10Gzt
redraw!
call assert_match('^\s\+01 10$', Screenline(1))
normal! 100Gzt
redraw!
call assert_match('^\s\+001 100$', Screenline(1))
normal! 1000Gzt
redraw!
call assert_match('^\s\+0001 1000$', Screenline(1))
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -5231,6 +5231,64 @@ func Test_qftextfunc()
call Xtest_qftextfunc('l')
endfunc
" Test for updating a location list for some other window and check that
" 'qftextfunc' uses the correct location list.
func Test_qftextfunc_other_loclist()
%bw!
call setloclist(0, [], 'f')
" create a window and a location list for it and open the location list
" window
lexpr ['F1:10:12:one', 'F1:20:14:two']
let w1_id = win_getid()
call setloclist(0, [], ' ',
\ {'lines': ['F1:10:12:one', 'F1:20:14:two'],
\ 'quickfixtextfunc':
\ {d -> map(getloclist(d.winid, {'id' : d.id,
\ 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
\ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
lwindow
let w2_id = win_getid()
" create another window and a location list for it and open the location
" list window
topleft new
let w3_id = win_getid()
call setloclist(0, [], ' ',
\ {'lines': ['F2:30:32:eleven', 'F2:40:34:twelve'],
\ 'quickfixtextfunc':
\ {d -> map(getloclist(d.winid, {'id' : d.id,
\ 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
\ "'Ligne ' .. v:val.lnum .. ', Colonne ' .. v:val.col")}})
lwindow
let w4_id = win_getid()
topleft new
lexpr ['F3:50:52:green', 'F3:60:54:blue']
let w5_id = win_getid()
" change the location list for some other window
call setloclist(0, [], 'r', {'lines': ['F3:55:56:aaa', 'F3:57:58:bbb']})
call setloclist(w1_id, [], 'r', {'lines': ['F1:62:63:bbb', 'F1:64:65:ccc']})
call setloclist(w3_id, [], 'r', {'lines': ['F2:76:77:ddd', 'F2:78:79:eee']})
call assert_equal(['Line 62, Col 63', 'Line 64, Col 65'],
\ getbufline(winbufnr(w2_id), 1, '$'))
call assert_equal(['Ligne 76, Colonne 77', 'Ligne 78, Colonne 79'],
\ getbufline(winbufnr(w4_id), 1, '$'))
call setloclist(w2_id, [], 'r', {'lines': ['F1:32:33:fff', 'F1:34:35:ggg']})
call setloclist(w4_id, [], 'r', {'lines': ['F2:46:47:hhh', 'F2:48:49:jjj']})
call assert_equal(['Line 32, Col 33', 'Line 34, Col 35'],
\ getbufline(winbufnr(w2_id), 1, '$'))
call assert_equal(['Ligne 46, Colonne 47', 'Ligne 48, Colonne 49'],
\ getbufline(winbufnr(w4_id), 1, '$'))
call win_gotoid(w5_id)
lwindow
call assert_equal(['F3|55 col 56| aaa', 'F3|57 col 58| bbb'],
\ getline(1, '$'))
%bw!
endfunc
" Running :lhelpgrep command more than once in a help window, doesn't jump to
" the help topic
func Test_lhelpgrep_from_help_window()

View File

@@ -111,4 +111,27 @@ func Test_si_comment_line_continuation()
close!
endfunc
" When 'paste' is set, 'smartindent' should not take effect.
func Test_si_with_paste()
new
setlocal smartindent autoindent
set paste
" insert text that will trigger smartindent
exe "norm! i {\nif (x)\ni = 1;\n#define FOO 1\nj = 2;\n}"
exe "norm! Ok = 3;"
exe "norm! 4G>>"
call assert_equal([' {', 'if (x)', 'i = 1;', '#define FOO 1',
\ 'j = 2;', 'k = 3;', '}'], getline(1, '$'))
call assert_true(&smartindent)
set nopaste
%d _
exe "norm! i {\nif (x)\ni = 1;\n#define FOO 1\nj = 2;\n}"
exe "norm! Ok = 3;"
exe "norm! 4G>>"
call assert_equal([' {', "\t if (x)", "\t\t i = 1;",
\ '#define FOO 1', "\t\t j = 2;", "\t k = 3;", ' }'],
\ getline(1, '$'))
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1301,4 +1301,20 @@ func Test_write_in_vimrc()
call delete('Xvimrc')
endfunc
func Test_echo_true_in_cmd()
CheckNotGui
let lines =<< trim END
echo v:true
call writefile(['done'], 'Xresult')
quit
END
call writefile(lines, 'Xscript')
if RunVim([], [], '--cmd "source Xscript"')
call assert_equal(['done'], readfile('Xresult'))
endif
call delete('Xscript')
call delete('Xresult')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1820,6 +1820,19 @@ def Test_assign_command_modifier()
CheckDefAndScriptSuccess(lines)
enddef
def Test_assign_alt_buf_register()
var lines =<< trim END
edit 'file_b1'
var b1 = bufnr()
edit 'file_b2'
var b2 = bufnr()
assert_equal(b1, bufnr('#'))
@# = b2
assert_equal(b2, bufnr('#'))
END
CheckDefAndScriptSuccess(lines)
enddef
def Test_script_funcref_case()
var lines =<< trim END
var Len = (s: string): number => len(s) + 1

View File

@@ -117,7 +117,7 @@ def Test_disassemble_exec_expr()
'\d 2STRING stack\[-1\]\_s*' ..
'\d\+ PUSHS ".txt"\_s*' ..
'\d\+ EXECCONCAT 4\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -133,7 +133,7 @@ EOF
assert_match('<SNR>\d*_PyHeredoc.*' ..
" python3 << EOF^@ print('hello')^@EOF\\_s*" ..
'\d EXEC_SPLIT python3 << EOF^@ print(''hello'')^@EOF\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
endif
@@ -153,7 +153,7 @@ def Test_disassemble_substitute()
'\d SUBSTITUTE :%s/a/\\=expr/&g#c\_s*' ..
' 0 LOAD $0\_s*' ..
' -------------\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -181,7 +181,7 @@ def Test_disassemble_seachpair()
' -------------\_s*' ..
'\d BCALL searchpair(argc 5)\_s*' ..
'\d DROP\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -209,7 +209,7 @@ def Test_disassemble_redir_var()
'\d REDIR END\_s*' ..
'\d CONCAT\_s*' ..
'\d STORE $0\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -228,7 +228,7 @@ def Test_disassemble_cexpr()
'\d CEXPR pre cexpr\_s*' ..
'\d LOAD $0\_s*' ..
'\d CEXPR core cexpr "cexpr errors"\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -244,7 +244,7 @@ def Test_disassemble_yank_range()
'\d EXEC norm! m\[jjm\]\_s*' ..
' :''\[,''\]yank\_s*' ..
'\d EXEC :''\[,''\]yank\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -258,7 +258,7 @@ def Test_disassemble_put_expr()
' :3put ="text"\_s*' ..
'\d PUSHS "text"\_s*' ..
'\d PUT = 3\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -272,7 +272,7 @@ def Test_disassemble_put_range()
' :$-2put a\_s*' ..
'\d RANGE $-2\_s*' ..
'\d PUT a range\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -390,7 +390,7 @@ def Test_disassemble_store_member()
'\d\+ PUSHNR 1\_s*' ..
'\d\+ LOAD $2\_s*' ..
'\d\+ STOREINDEX blob\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -413,7 +413,7 @@ def Test_disassemble_store_index()
'\d LOAD $0\_s*' ..
'\d MEMBER dd\_s*' ..
'\d STOREINDEX any\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -448,7 +448,7 @@ def Test_disassemble_list_assign()
'\d\+ STORE $1\_s*' ..
'\d\+ SLICE 2\_s*' ..
'\d\+ STORE $2\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -476,7 +476,7 @@ def Test_disassemble_list_add()
'\d\+ CHECKTYPE number stack\[-1\]\_s*' ..
'\d\+ LISTAPPEND\_s*' ..
'\d\+ DROP\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -503,7 +503,7 @@ def Test_disassemble_blob_add()
'\d\+ CHECKTYPE number stack\[-1\]\_s*' ..
'\d\+ BLOBAPPEND\_s*' ..
'\d\+ DROP\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -530,7 +530,7 @@ def Test_disassemble_blob_index_slice()
'\d\+ PUSHNR 2\_s*' ..
'\d\+ BLOBSLICE\_s*' ..
'\d\+ ECHO 1\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -720,7 +720,7 @@ def Test_disassemble_closure()
'\d LOAD arg\[-1\]\_s*' ..
'\d CONCAT\_s*' ..
'\d STOREOUTER level 1 $0\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
res = execute('disass g:Get')
@@ -754,7 +754,7 @@ def Test_disassemble_pcall()
'\d PCALL top (argc 1)\_s*' ..
'\d PCALL end\_s*' ..
'\d DROP\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -1012,7 +1012,7 @@ def Test_disassemble_function()
'\d PUSHS "UserFunc"\_s*' ..
'\d BCALL funcref(argc 1)\_s*' ..
'\d STORE $2\_s*' ..
'\d RETURN 0',
'\d RETURN void',
instr)
enddef
@@ -1039,7 +1039,7 @@ def Test_disassemble_channel()
'var chan1: channel\_s*' ..
'\d PUSHCHANNEL 0\_s*' ..
'\d STORE $2\_s*' ..
'\d RETURN 0',
'\d RETURN void',
instr)
enddef
@@ -1111,7 +1111,7 @@ def Test_disassemble_nested_func()
'echomsg "inner"\_s*' ..
'enddef\_s*' ..
'\d NEWFUNC <lambda>\d\+ Inner\_s*' ..
'\d RETURN 0',
'\d RETURN void',
instr)
enddef
@@ -1133,7 +1133,7 @@ def Test_disassemble_nested_def_list()
'\d DEF /Info\_s*' ..
'def /Info/\_s*' ..
'\d DEF /Info/\_s*' ..
'\d RETURN 0',
'\d RETURN void',
instr)
enddef
@@ -1264,7 +1264,7 @@ def Test_disassemble_for_loop_unpack()
'endfor\_s*' ..
'\d\+ JUMP -> 8\_s*' ..
'\d\+ DROP\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
instr)
enddef
@@ -1321,7 +1321,7 @@ def Test_disassemble_for_loop_continue()
'endfor\_s*' ..
'21 JUMP -> 4\_s*' ..
'\d\+ DROP\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
instr)
enddef
@@ -1341,7 +1341,7 @@ def Test_disassemble_typecast()
'\d NEWLIST size 2\_s*' ..
'\d SETTYPE list<number>\_s*' ..
'\d STORE $0\_s*' ..
'\d RETURN 0\_s*',
'\d RETURN void\_s*',
instr)
enddef
@@ -1828,7 +1828,7 @@ def Test_dsassemble_falsy_op()
'echo "" ?? "empty string"\_s*' ..
'\d\+ PUSHS "empty string"\_s*' ..
'\d\+ ECHO 1\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -1855,7 +1855,7 @@ def Test_disassemble_compare_const()
'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*' ..
'\d PUSHNR 42.*' ..
'\d ECHO 1.*' ..
'\d RETURN 0',
'\d RETURN void',
instr)
else
# condition false, function just returns
@@ -1863,7 +1863,7 @@ def Test_disassemble_compare_const()
'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '[ \n]*' ..
'echo 42[ \n]*' ..
'endif[ \n]*' ..
'\d RETURN 0',
'\d RETURN void',
instr)
endif
@@ -1901,7 +1901,7 @@ def Test_disassemble_execute()
'\d\+ LOAD $1\_s*' ..
'\d\+ CONCAT\_s*' ..
'\d\+ EXECUTE 1\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -1920,7 +1920,7 @@ def Test_disassemble_echomsg()
"echoerr 'went' .. 'wrong'\\_s*" ..
'\d PUSHS "wentwrong"\_s*' ..
'\d ECHOERR 1\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -2029,7 +2029,7 @@ def Test_shuffle()
'\d SHUFFLE 2 up 1\_s*' ..
'\d BCALL append(argc 2)\_s*' ..
'\d DROP\_s*' ..
'\d RETURN 0',
'\d RETURN void',
res)
enddef
@@ -2052,7 +2052,7 @@ def Test_silent()
'\d PUSHS "error"\_s*' ..
'\d ECHOERR 1\_s*' ..
'\d CMDMOD_REV\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -2081,7 +2081,7 @@ def Test_silent_if()
'\d\+ CMDMOD_REV\_s*' ..
'\d\+ JUMP_IF_FALSE -> \d\+\_s*' ..
'endif\_s*' ..
'\d\+ RETURN 0',
'\d\+ RETURN void',
res)
enddef
@@ -2104,7 +2104,7 @@ def Test_silent_for()
'endfor\_s*' ..
'\d JUMP -> 5\_s*' ..
'8 DROP\_s*' ..
'\d RETURN 0\_s*',
'\d RETURN void\_s*',
res)
enddef
@@ -2125,7 +2125,7 @@ def Test_silent_while()
'endwhile\_s*' ..
'\d JUMP -> 0\_s*' ..
'6 RETURN 0\_s*',
'6 RETURN void\_s*',
res)
enddef

View File

@@ -2340,7 +2340,7 @@ def Test_expr7_dict()
CheckScriptFailure(['vim9script', "var x = {xxx: 1,"], 'E723:', 2)
CheckDefAndScriptFailure2(["var x = {['a']: xxx}"], 'E1001:', 'E121:', 1)
CheckDefAndScriptFailure(["var x = {a: 1, a: 2}"], 'E721:', 1)
CheckDefExecAndScriptFailure2(["var x = g:anint.member"], 'E715:', 'E15:', 1)
CheckDefExecAndScriptFailure2(["var x = g:anint.member"], 'E715:', 'E488:', 1)
CheckDefExecAndScriptFailure(["var x = g:dict_empty.member"], 'E716:', 1)
CheckDefExecAndScriptFailure(['var x: dict<number> = {a: 234, b: "1"}'], 'E1012:', 1)
@@ -2967,6 +2967,20 @@ def Test_expr7_method_call()
assert_equal([1, 2, 3], sorted)
END
CheckDefAndScriptSuccess(lines)
lines =<< trim END
def RetVoid()
enddef
RetVoid()->byte2line()
END
CheckDefExecAndScriptFailure(lines, 'E1031:')
lines =<< trim END
def RetVoid()
enddef
RetVoid()->byteidx(3)
END
CheckDefExecAndScriptFailure(lines, 'E1031:')
enddef
@@ -3038,7 +3052,7 @@ func Test_expr7_fails()
call CheckDefAndScriptFailure2(["var x = [notfound]"], "E1001:", 'E121:', 1)
call CheckDefAndScriptFailure2(["var X = () => 123)"], "E488:", 'E15:', 1)
call CheckDefAndScriptFailure(["var X = () => 123)"], 'E488:', 1)
call CheckDefAndScriptFailure(["var x = 123->((x) => x + 5)"], "E107:", 1)
call CheckDefAndScriptFailure(["var x = &notexist"], 'E113:', 1)
@@ -3056,7 +3070,7 @@ func Test_expr7_fails()
call CheckDefExecAndScriptFailure(["var x = +g:alist"], 'E745:', 1)
call CheckDefExecAndScriptFailure(["var x = +g:adict"], 'E728:', 1)
call CheckDefAndScriptFailure2(["var x = ''", "var y = x.memb"], 'E715:', 'E15:', 2)
call CheckDefAndScriptFailure2(["var x = ''", "var y = x.memb"], 'E715:', 'E488:', 2)
call CheckDefAndScriptFailure2(["'yes'->", "Echo()"], 'E488: Trailing characters: ->', 'E260: Missing name after ->', 1)
@@ -3340,8 +3354,8 @@ func Test_expr7_trailing_fails()
endfunc
func Test_expr_fails()
call CheckDefAndScriptFailure2(["var x = '1'is2"], 'E488:', 'E15:', 1)
call CheckDefAndScriptFailure2(["var x = '1'isnot2"], 'E488:', 'E15:', 1)
call CheckDefAndScriptFailure(["var x = '1'is2"], 'E488:', 1)
call CheckDefAndScriptFailure(["var x = '1'isnot2"], 'E488:', 1)
call CheckDefAndScriptFailure2(["CallMe ('yes')"], 'E476:', 'E492:', 1)

View File

@@ -590,6 +590,19 @@ def Test_try_catch_throw()
return 2
enddef
assert_equal(4, ReturnInFinally())
var lines =<< trim END
vim9script
try
acos('0.5')
->setline(1)
catch
g:caught = v:exception
endtry
END
CheckScriptSuccess(lines)
assert_match('E808: Number or Float required', g:caught)
unlet g:caught
enddef
" :while at the very start of a function that :continue jumps to
@@ -3199,7 +3212,7 @@ def Test_vim9_comment_not_compiled()
'if 1# comment3',
' echo "yes"',
'endif',
], 'E15:')
], 'E488:')
CheckScriptFailure([
'vim9script',
@@ -3208,7 +3221,7 @@ def Test_vim9_comment_not_compiled()
'elseif 2#comment',
' echo "no"',
'endif',
], 'E15:')
], 'E488:')
CheckScriptSuccess([
'vim9script',
@@ -3218,7 +3231,7 @@ def Test_vim9_comment_not_compiled()
CheckScriptFailure([
'vim9script',
'var v = 1# comment6',
], 'E15:')
], 'E488:')
CheckScriptSuccess([
'vim9script',

View File

@@ -4,7 +4,7 @@ source check.vim
source term_util.vim
source shared.vim
function Test_viminfo_read_and_write()
func Test_viminfo_read_and_write()
" First clear 'history', so that "hislen" is zero. Then set it again,
" simulating Vim starting up.
set history=0
@@ -12,6 +12,7 @@ function Test_viminfo_read_and_write()
set history=1000
call histdel(':')
let @/=''
let lines = [
\ '# comment line',
\ '*encoding=utf-8',
@@ -89,6 +90,36 @@ func Test_global_vars()
call assert_equal(test_null, g:MY_GLOBAL_NULL)
call assert_equal(test_none, g:MY_GLOBAL_NONE)
" When reading global variables from viminfo, if a variable cannot be
" modified, then the value should not be changed.
unlet g:MY_GLOBAL_STRING
unlet g:MY_GLOBAL_NUM
unlet g:MY_GLOBAL_FLOAT
unlet g:MY_GLOBAL_DICT
unlet g:MY_GLOBAL_LIST
unlet g:MY_GLOBAL_BLOB
const g:MY_GLOBAL_STRING = 'New Value'
const g:MY_GLOBAL_NUM = 987
const g:MY_GLOBAL_FLOAT = 1.16
const g:MY_GLOBAL_DICT = {'editor': 'vim'}
const g:MY_GLOBAL_LIST = [5, 7, 13]
const g:MY_GLOBAL_BLOB = 0zDEADBEEF
call assert_fails('rv! Xviminfo', 'E741:')
call assert_equal('New Value', g:MY_GLOBAL_STRING)
call assert_equal(987, g:MY_GLOBAL_NUM)
call assert_equal(1.16, g:MY_GLOBAL_FLOAT)
call assert_equal({'editor': 'vim'}, g:MY_GLOBAL_DICT)
call assert_equal([5, 7 , 13], g:MY_GLOBAL_LIST)
call assert_equal(0zDEADBEEF, g:MY_GLOBAL_BLOB)
unlet g:MY_GLOBAL_STRING
unlet g:MY_GLOBAL_NUM
unlet g:MY_GLOBAL_FLOAT
unlet g:MY_GLOBAL_DICT
unlet g:MY_GLOBAL_LIST
unlet g:MY_GLOBAL_BLOB
" Test for invalid values for a blob, list, dict in a viminfo file
call writefile([
\ "!GLOB_BLOB_1\tBLO\t123",
@@ -97,7 +128,7 @@ func Test_global_vars()
\ "!GLOB_BLOB_4\tBLO\t0z12 ab",
\ "!GLOB_LIST_1\tLIS\t1 2",
\ "!GLOB_DICT_1\tDIC\t1 2"], 'Xviminfo')
call assert_fails('rv! Xviminfo', 'E15:')
call assert_fails('rv! Xviminfo', 'E488:')
call assert_equal('123', g:GLOB_BLOB_1)
call assert_equal(1, type(g:GLOB_BLOB_1))
call assert_equal('012', g:GLOB_BLOB_2)
@@ -510,6 +541,20 @@ func Test_viminfo_bad_syntax()
call delete('Xviminfo')
endfunc
func Test_viminfo_bad_register_syntax()
let lines = []
call add(lines, '|1,4')
call add(lines, '|3') " invalid number of fields for a register type
call add(lines, '|3,1,1,1,1,,1,"x"') " invalid value for the width field
call add(lines, '|3,0,80,1,1,1,1,"x"') " invalid register number
call add(lines, '|3,0,10,5,1,1,1,"x"') " invalid register type
call add(lines, '|3,0,10,1,20,1,1,"x"') " invalid line count
call add(lines, '|3,0,10,1,0,1,1') " zero line count
call writefile(lines, 'Xviminfo')
rviminfo Xviminfo
call delete('Xviminfo')
endfunc
func Test_viminfo_file_marks()
silent! bwipe test_viminfo.vim
silent! bwipe Xviminfo
@@ -664,6 +709,7 @@ func Test_viminfo_bufferlist()
" If there are arguments, then :rviminfo doesn't read the buffer list.
" Need to delete all the arguments for :rviminfo to work.
%argdelete
set viminfo&vim
edit Xfile1
edit Xfile2
@@ -684,9 +730,42 @@ func Test_viminfo_bufferlist()
call assert_equal('Xfile1', bufname(l[1].bufnr))
call assert_equal('Xfile2', bufname(l[2].bufnr))
" The quickfix, terminal, unlisted, unnamed buffers are not stored in the
" viminfo file
%bw!
edit Xfile1
new
setlocal nobuflisted
new
copen
if has('terminal')
terminal
endif
wviminfo! Xviminfo
%bwipe!
rviminfo Xviminfo
let l = getbufinfo()
call assert_equal(2, len(l))
call assert_true(bufexists('Xfile1'))
" If a count is specified for '%', then only that many buffers should be
" stored in the viminfo file.
%bw!
set viminfo&vim
new Xbuf1
new Xbuf2
set viminfo+=%1
wviminfo! Xviminfo
%bwipe!
rviminfo! Xviminfo
let l = getbufinfo()
call assert_equal(2, len(l))
call assert_true(bufexists('Xbuf1'))
call assert_false(bufexists('Xbuf2'))
call delete('Xviminfo')
%bwipe
set viminfo-=%
set viminfo&vim
endfunc
" Test for errors in a viminfo file
@@ -747,6 +826,12 @@ func Test_viminfo_registers_old()
\ ' Vim',
\ '"a CHAR 0',
\ ' red',
\ '"c BLOCK 0',
\ ' a',
\ ' d',
\ '"d LINE 0',
\ ' abc',
\ ' def',
\ '"m@ CHAR 0',
\ " :echo 'Hello'\<CR>",
\ "",
@@ -760,7 +845,12 @@ func Test_viminfo_registers_old()
silent! normal @t
rviminfo! Xviminfo
call assert_equal('red', getreg('a'))
call assert_equal("v", getregtype('a'))
call assert_equal('two', getreg('b'))
call assert_equal("a\nd", getreg('c'))
call assert_equal("\<C-V>1", getregtype('c'))
call assert_equal("abc\ndef\n", getreg('d'))
call assert_equal("V", getregtype('d'))
call assert_equal(":echo 'Hello'\<CR>", getreg('m'))
call assert_equal('Vim', getreg('"'))
call assert_equal("\nHello", execute('normal @@'))
@@ -914,4 +1004,228 @@ func Test_viminfo_oldfiles_newfile()
let &viminfofile = save_viminfofile
endfunc
" When writing CTRL-V or "\n" to a viminfo file, it is converted to CTRL-V
" CTRL-V and CTRL-V n respectively.
func Test_viminfo_with_Ctrl_V()
silent! exe "normal! /\<C-V>\<C-V>\n"
wviminfo Xviminfo
call assert_notequal(-1, readfile('Xviminfo')->index("?/\<C-V>\<C-V>"))
let @/ = 'abc'
rviminfo! Xviminfo
call assert_equal("\<C-V>", @/)
silent! exe "normal! /\<C-V>\<C-J>\n"
wviminfo Xviminfo
call assert_notequal(-1, readfile('Xviminfo')->index("?/\<C-V>n"))
let @/ = 'abc'
rviminfo! Xviminfo
call assert_equal("\n", @/)
call delete('Xviminfo')
endfunc
" Test for the 'r' field in 'viminfo' (removal media)
func Test_viminfo_removable_media()
CheckUnix
if !isdirectory('/tmp') || getftype('/tmp') != 'dir'
return
endif
let save_viminfo = &viminfo
set viminfo+=r/tmp
edit /tmp/Xvima1b2c3
wviminfo Xviminfo
let matches = readfile('Xviminfo')->filter("v:val =~ 'Xvima1b2c3'")
call assert_equal(0, matches->len())
let &viminfo = save_viminfo
call delete('Xviminfo')
endfunc
" Test for the 'h' flag in 'viminfo'. If 'h' is not present, then the last
" search pattern read from 'viminfo' should be highlighted with 'hlsearch'.
" If 'h' is present, then the last search pattern should not be highlighted.
func Test_viminfo_hlsearch()
set viminfo&vim
new
call setline(1, ['one two three'])
" save the screen attribute for the Search highlighted text and the normal
" text for later comparison
set hlsearch
let @/ = 'three'
redraw!
let hiSearch = screenattr(1, 9)
let hiNormal = screenattr(1, 1)
set viminfo-=h
let @/='two'
wviminfo! Xviminfo
let @/='one'
rviminfo! Xviminfo
redraw!
call assert_equal(hiSearch, screenattr(1, 5))
call assert_equal(hiSearch, screenattr(1, 6))
call assert_equal(hiSearch, screenattr(1, 7))
set viminfo+=h
let @/='two'
wviminfo! Xviminfo
let @/='one'
rviminfo! Xviminfo
redraw!
call assert_equal(hiNormal, screenattr(1, 5))
call assert_equal(hiNormal, screenattr(1, 6))
call assert_equal(hiNormal, screenattr(1, 7))
call delete('Xviminfo')
set hlsearch& viminfo&vim
bw!
endfunc
" Test for restoring the magicness of the last search pattern from the viminfo
" file.
func Test_viminfo_last_spat_magic()
set viminfo&vim
new
call setline(1, ' one abc a.c')
" restore 'nomagic'
set nomagic
exe "normal gg/a.c\<CR>"
wviminfo! Xviminfo
set magic
exe "normal gg/one\<CR>"
rviminfo! Xviminfo
exe "normal! gg/\<CR>"
call assert_equal(10, col('.'))
" restore 'magic'
set magic
exe "normal gg/a.c\<CR>"
wviminfo! Xviminfo
set nomagic
exe "normal gg/one\<CR>"
rviminfo! Xviminfo
exe "normal! gg/\<CR>"
call assert_equal(6, col('.'))
call delete('Xviminfo')
set viminfo&vim magic&
bw!
endfunc
" Test for restoring the smartcase of the last search pattern from the viminfo
" file.
func Test_viminfo_last_spat_smartcase()
new
call setline(1, ' one abc Abc')
set ignorecase smartcase
" Searching with * should disable smartcase
exe "normal! gg$b*"
wviminfo! Xviminfo
exe "normal gg/one\<CR>"
rviminfo! Xviminfo
exe "normal! gg/\<CR>"
call assert_equal(6, col('.'))
call delete('Xviminfo')
set ignorecase& smartcase& viminfo&
bw!
endfunc
" Test for restoring the last search pattern with a line or character offset
" from the viminfo file.
func Test_viminfo_last_spat_offset()
new
call setline(1, ['one', 'two', 'three', 'four', 'five'])
" line offset
exe "normal! /two/+2\<CR>"
wviminfo! Xviminfo
exe "normal gg/five\<CR>"
rviminfo! Xviminfo
exe "normal! gg/\<CR>"
call assert_equal(4, line('.'))
" character offset
exe "normal! gg/^th/e+2\<CR>"
wviminfo! Xviminfo
exe "normal gg/two\<CR>"
rviminfo! Xviminfo
exe "normal! gg/\<CR>"
call assert_equal([3, 4], [line('.'), col('.')])
call delete('Xviminfo')
bw!
endfunc
" Test for saving and restoring the last executed register (@ command)
" from the viminfo file
func Test_viminfo_last_exec_reg()
let g:val = 1
let @a = ":let g:val += 1\n"
normal! @a
wviminfo! Xviminfo
let @b = ''
normal! @b
rviminfo! Xviminfo
normal @@
call assert_equal(3, g:val)
call delete('Xviminfo')
endfunc
" Test for merging file marks in a viminfo file
func Test_viminfo_merge_file_marks()
for [f, l, t] in [['a.txt', 5, 10], ['b.txt', 10, 20]]
call test_settime(t)
exe 'edit ' .. f
call setline(1, range(1, 20))
exe l . 'mark a'
wviminfo Xviminfo
bw!
endfor
call test_settime(30)
for [f, l] in [['a.txt', 5], ['b.txt', 10]]
exe 'edit ' .. f
rviminfo! Xviminfo
call assert_equal(l, line("'a"))
bw!
endfor
call delete('Xviminfo')
call test_settime(0)
endfunc
" Test for merging file marks from a old viminfo file
func Test_viminfo_merge_old_filemarks()
let lines = []
call add(lines, '|1,4')
call add(lines, '> ' .. fnamemodify('a.txt', ':p:~'))
call add(lines, "\tb\t7\t0\n")
call writefile(lines, 'Xviminfo')
edit b.txt
call setline(1, range(1, 20))
12mark b
wviminfo Xviminfo
bw!
edit a.txt
rviminfo! Xviminfo
call assert_equal(7, line("'b"))
edit b.txt
rviminfo! Xviminfo
call assert_equal(12, line("'b"))
call delete('Xviminfo')
endfunc
" Test for merging the jump list from a old viminfo file
func Test_viminfo_merge_old_jumplist()
let lines = []
call add(lines, "-' 10 1 " .. fnamemodify('a.txt', ':p:~'))
call add(lines, "-' 20 1 " .. fnamemodify('a.txt', ':p:~'))
call add(lines, "-' 30 1 " .. fnamemodify('b.txt', ':p:~'))
call add(lines, "-' 40 1 " .. fnamemodify('b.txt', ':p:~'))
call writefile(lines, 'Xviminfo')
clearjumps
rviminfo! Xviminfo
let l = getjumplist()[0]
call assert_equal([40, 30, 20, 10], [l[0].lnum, l[1].lnum, l[2].lnum,
\ l[3].lnum])
bw!
call delete('Xviminfo')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -5570,7 +5570,7 @@ func Test_expr_eval_error_msg()
call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
call T(22, '1 2 + CONT(22)', 'E488', "Trailing characters: 2 +")
call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")

View File

@@ -238,9 +238,11 @@ tv_get_bool_or_number_chk(typval_T *varp, int *denote, int want_bool)
case VAR_BLOB:
emsg(_("E974: Using a Blob as a Number"));
break;
case VAR_VOID:
emsg(_(e_cannot_use_void_value));
break;
case VAR_UNKNOWN:
case VAR_ANY:
case VAR_VOID:
case VAR_INSTR:
internal_error_no_abort("tv_get_number(UNKNOWN)");
break;
@@ -294,7 +296,7 @@ tv_get_bool_chk(typval_T *varp, int *denote)
return tv_get_bool_or_number_chk(varp, denote, TRUE);
}
#ifdef FEAT_FLOAT
#if defined(FEAT_FLOAT) || defined(PROTO)
float_T
tv_get_float(typval_T *varp)
{
@@ -336,9 +338,11 @@ tv_get_float(typval_T *varp)
case VAR_BLOB:
emsg(_("E975: Using a Blob as a Float"));
break;
case VAR_VOID:
emsg(_(e_cannot_use_void_value));
break;
case VAR_UNKNOWN:
case VAR_ANY:
case VAR_VOID:
case VAR_INSTR:
internal_error_no_abort("tv_get_float(UNKNOWN)");
break;
@@ -501,9 +505,11 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
return channel_to_string_buf(varp, buf);
#endif
break;
case VAR_VOID:
emsg(_(e_cannot_use_void_value));
break;
case VAR_UNKNOWN:
case VAR_ANY:
case VAR_VOID:
case VAR_INSTR:
semsg(_(e_using_invalid_value_as_string_str),
vartype_name(varp->v_type));
@@ -657,9 +663,11 @@ copy_tv(typval_T *from, typval_T *to)
++to->vval.v_dict->dv_refcount;
}
break;
case VAR_VOID:
emsg(_(e_cannot_use_void_value));
break;
case VAR_UNKNOWN:
case VAR_ANY:
case VAR_VOID:
internal_error_no_abort("copy_tv(UNKNOWN)");
break;
}

View File

@@ -750,6 +750,36 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3018,
/**/
3017,
/**/
3016,
/**/
3015,
/**/
3014,
/**/
3013,
/**/
3012,
/**/
3011,
/**/
3010,
/**/
3009,
/**/
3008,
/**/
3007,
/**/
3006,
/**/
3005,
/**/
3004,
/**/
3003,
/**/

View File

@@ -91,7 +91,7 @@ typedef enum {
ISN_PCALL, // call partial, use isn_arg.pfunc
ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set
ISN_RETURN, // return, result is on top of stack
ISN_RETURN_ZERO, // Push zero, then return
ISN_RETURN_VOID, // Push void, then return
ISN_FUNCREF, // push a function ref to dfunc isn_arg.funcref
ISN_NEWFUNC, // create a global function from a lambda function
ISN_DEF, // list functions

View File

@@ -5852,7 +5852,7 @@ get_var_dest(
return FAIL;
}
*dest = dest_reg;
*type = &t_string;
*type = name[1] == '#' ? &t_number_or_string : &t_string;
}
else if (STRNCMP(name, "g:", 2) == 0)
{
@@ -5927,7 +5927,8 @@ generate_store_var(
case dest_env:
return generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
case dest_reg:
return generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
return generate_STORE(cctx, ISN_STOREREG,
name[1] == '@' ? '"' : name[1], NULL);
case dest_vimvar:
return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
case dest_script:
@@ -6843,9 +6844,19 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
goto theend;
}
}
else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type,
else
{
type_T *lhs_type = lhs.lhs_member_type;
// Special case: assigning to @# can use a number or a
// string.
if (lhs_type == &t_number_or_string
&& rhs_type->tt_type == VAR_NUMBER)
lhs_type = &t_number;
if (*p != '=' && need_type(rhs_type, lhs_type,
-1, 0, cctx, FALSE, FALSE) == FAIL)
goto theend;
}
}
else if (cmdidx == CMD_final)
{
@@ -7711,6 +7722,7 @@ compile_for(char_u *arg_start, cctx_T *cctx)
int semicolon = FALSE;
size_t varlen;
garray_T *stack = &cctx->ctx_type_stack;
garray_T *instr = &cctx->ctx_instr;
scope_T *scope;
lvar_T *loop_lvar; // loop iteration variable
lvar_T *var_lvar; // variable for "var"
@@ -7737,6 +7749,13 @@ compile_for(char_u *arg_start, cctx_T *cctx)
if (may_get_next_line_error(wp, &p, cctx) == FAIL)
return NULL;
// Remove the already generated ISN_DEBUG, it is written below the ISN_FOR
// instruction.
if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
.isn_type == ISN_DEBUG)
--instr->ga_len;
scope = new_scope(cctx, FOR_SCOPE);
if (scope == NULL)
return NULL;
@@ -7788,11 +7807,12 @@ compile_for(char_u *arg_start, cctx_T *cctx)
item_type = vartype->tt_member->tt_member;
}
// CMDMOD_REV must come before the FOR instruction
// CMDMOD_REV must come before the FOR instruction.
generate_undo_cmdmods(cctx);
// "for_end" is set when ":endfor" is found
scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
generate_FOR(cctx, loop_lvar->lv_idx);
arg = arg_start;
@@ -7893,6 +7913,10 @@ compile_for(char_u *arg_start, cctx_T *cctx)
vim_free(name);
}
if (cctx->ctx_compile_type == CT_DEBUG)
// Add ISN_DEBUG here, so that the loop variables can be inspected.
generate_instr_debug(cctx);
return arg_end;
failed:
@@ -7927,7 +7951,7 @@ compile_endfor(char_u *arg, cctx_T *cctx)
// At end of ":for" scope jump back to the FOR instruction.
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
// Fill in the "end" label in the FOR statement so it can jump here
// Fill in the "end" label in the FOR statement so it can jump here.
isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
isn->isn_arg.forloop.for_end = instr->ga_len;
@@ -8234,6 +8258,7 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
#ifdef FEAT_PROFILE
// the profile-start should be after the jump
if (cctx->ctx_compile_type == CT_PROFILE
&& instr->ga_len > 0
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
.isn_type == ISN_PROF_START)
--instr->ga_len;
@@ -9679,8 +9704,8 @@ nextline:
goto erret;
}
// Return zero if there is no return at the end.
generate_instr(&cctx, ISN_RETURN_ZERO);
// Return void if there is no return at the end.
generate_instr(&cctx, ISN_RETURN_VOID);
}
// When compiled with ":silent!" and there was an error don't consider the
@@ -10047,7 +10072,7 @@ delete_instr(isn_T *isn)
case ISN_REDIREND:
case ISN_REDIRSTART:
case ISN_RETURN:
case ISN_RETURN_ZERO:
case ISN_RETURN_VOID:
case ISN_SHUFFLE:
case ISN_SLICE:
case ISN_STORE:

View File

@@ -1394,7 +1394,7 @@ typedef struct subs_expr_S {
// Set when calling do_debug().
static ectx_T *debug_context = NULL;
static int debug_arg_count;
static int debug_var_count;
/*
* When debugging lookup "name" and return the typeval.
@@ -1405,23 +1405,86 @@ lookup_debug_var(char_u *name)
{
int idx;
dfunc_T *dfunc;
ufunc_T *ufunc;
ectx_T *ectx = debug_context;
int varargs_off;
if (ectx == NULL)
return NULL;
dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
// Go through the local variable names, from last to first.
for (idx = debug_arg_count - 1; idx >= 0; --idx)
for (idx = debug_var_count - 1; idx >= 0; --idx)
{
char_u *s = ((char_u **)dfunc->df_var_names.ga_data)[idx];
if (STRCMP(s, name) == 0)
if (STRCMP(((char_u **)dfunc->df_var_names.ga_data)[idx], name) == 0)
return STACK_TV_VAR(idx);
}
// Go through argument names.
ufunc = dfunc->df_ufunc;
varargs_off = ufunc->uf_va_name == NULL ? 0 : 1;
for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx)
if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0)
return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len
- varargs_off + idx);
if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0)
return STACK_TV(ectx->ec_frame_idx - 1);
return NULL;
}
static void
handle_debug(isn_T *iptr, ectx_T *ectx)
{
char_u *line;
ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
+ ectx->ec_dfunc_idx)->df_ufunc;
isn_T *ni;
int end_lnum = iptr->isn_lnum;
garray_T ga;
int lnum;
SOURCING_LNUM = iptr->isn_lnum;
debug_context = ectx;
debug_var_count = iptr->isn_arg.number;
for (ni = iptr + 1; ni->isn_type != ISN_FINISH; ++ni)
if (ni->isn_type == ISN_DEBUG
|| ni->isn_type == ISN_RETURN
|| ni->isn_type == ISN_RETURN_VOID)
{
end_lnum = ni->isn_lnum;
break;
}
if (end_lnum > iptr->isn_lnum)
{
ga_init2(&ga, sizeof(char_u *), 10);
for (lnum = iptr->isn_lnum; lnum < end_lnum; ++lnum)
{
char_u *p = skipwhite(
((char_u **)ufunc->uf_lines.ga_data)[lnum - 1]);
if (*p == '#')
break;
if (ga_grow(&ga, 1) == OK)
((char_u **)(ga.ga_data))[ga.ga_len++] = p;
if (STRNCMP(p, "def ", 4) == 0)
break;
}
line = ga_concat_strings(&ga, " ");
vim_free(ga.ga_data);
}
else
line = ((char_u **)ufunc->uf_lines.ga_data)[iptr->isn_lnum - 1];
do_debug(line == NULL ? (char_u *)"[empty]" : line);
debug_context = NULL;
if (end_lnum > iptr->isn_lnum)
vim_free(line);
}
/*
* Execute instructions in execution context "ectx".
* Return OK or FAIL;
@@ -2127,8 +2190,7 @@ exec_instructions(ectx_T *ectx)
--ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(0);
write_reg_contents(reg == '@' ? '"' : reg,
tv_get_string(tv), -1, FALSE);
write_reg_contents(reg, tv_get_string(tv), -1, FALSE);
clear_tv(tv);
}
break;
@@ -2815,17 +2877,18 @@ exec_instructions(ectx_T *ectx)
}
break;
// return from a :def function call
case ISN_RETURN_ZERO:
// return from a :def function call without a value
case ISN_RETURN_VOID:
if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
++ectx->ec_stack.ga_len;
tv->v_type = VAR_NUMBER;
tv->v_type = VAR_VOID;
tv->vval.v_number = 0;
tv->v_lock = 0;
// FALLTHROUGH
// return from a :def function call with what is on the stack
case ISN_RETURN:
{
garray_T *trystack = &ectx->ec_trystack;
@@ -4144,21 +4207,7 @@ exec_instructions(ectx_T *ectx)
case ISN_DEBUG:
if (ex_nesting_level <= debug_break_level)
{
char_u *line;
ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
+ ectx->ec_dfunc_idx)->df_ufunc;
SOURCING_LNUM = iptr->isn_lnum;
debug_context = ectx;
debug_arg_count = iptr->isn_arg.number;
line = ((char_u **)ufunc->uf_lines.ga_data)[
iptr->isn_lnum - 1];
if (line == NULL)
line = (char_u *)"[empty]";
do_debug(line);
debug_context = NULL;
}
handle_debug(iptr, ectx);
break;
case ISN_SHUFFLE:
@@ -5076,8 +5125,8 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_RETURN:
smsg("%s%4d RETURN", pfx, current);
break;
case ISN_RETURN_ZERO:
smsg("%s%4d RETURN 0", pfx, current);
case ISN_RETURN_VOID:
smsg("%s%4d RETURN void", pfx, current);
break;
case ISN_FUNCREF:
{