Compare commits

...

11 Commits

Author SHA1 Message Date
Bram Moolenaar
97f227d9c9 patch 8.2.3105: Vim9: type of partial is wrong when it has arguments
Problem:    Vim9: type of partial is wrong when it has arguments.
Solution:   Subtract arguments from the count. (issue #8492)
2021-07-04 20:20:52 +02:00
Bram Moolenaar
b7480cd893 patch 8.2.3104: Vim9: unspecified function type causes type error
Problem:    Vim9: unspecified function type causes type error.
Solution:   Don't check type when min_argcount is negative. (issue #8492)
2021-07-04 18:28:15 +02:00
Bram Moolenaar
f33cae6050 patch 8.2.3103: swap test may fail on some systems
Problem:    Swap test may fail on some systems when jobs take longer to exit.
Solution:   Use different file names.
2021-07-04 17:36:54 +02:00
Bram Moolenaar
3777d6e32b patch 8.2.3102: test for crash fix does not fail without the fix
Problem:    Test for crash fix does not fail without the fix.
Solution:   Adjust the test sequence. (closes #8506)
2021-07-04 17:23:25 +02:00
Bram Moolenaar
26e88ec8e2 patch 8.2.3101: missing function prototype for vim_round()
Problem:    Missing function prototype for vim_round().
Solution:   Add the prototype
2021-07-04 17:21:04 +02:00
Bram Moolenaar
67b17a6fc6 patch 8.2.3101: missing function prototype for vim_round()
Problem:    Missing function prototype for vim_round().
Solution:   Add the prototype.
2021-07-04 16:50:55 +02:00
Bram Moolenaar
7a40ff00ed patch 8.2.3100: Vim9: no error when using type with unknown number of args
Problem:    Vim9: no error when using type with unknown number of arguments.
Solution:   Do not ignore argument count of -1. (closes #8492)
2021-07-04 15:54:08 +02:00
Bram Moolenaar
4197828dc6 patch 8.2.3099: Vim9: missing catch/finally not reported at script level
Problem:    Vim9: missing catch/finally not reported at script level.
Solution:   Give an error. (closes #8487)
2021-07-04 14:47:30 +02:00
Bram Moolenaar
999db2346b patch 8.2.3098: popup window test is flaky on MS-Windows with GUI
Problem:    Popup window test is flaky on MS-Windows with GUI.
Solution:   Skip the check in this situation.
2021-07-04 14:00:55 +02:00
Bram Moolenaar
1d97efce0c patch 8.2.3097: crash when using "quit" at recovery prompt
Problem:    Crash when using "quit" at recovery prompt and autocommands are
            triggered.
Solution:   Block autocommands when creating an empty buffer to use as the
            current buffer. (closes #8506)
2021-07-04 13:27:11 +02:00
Dominique Pelle
6c72fd51a8 patch 8.2.3096: temp files remain after running tests
Problem:    Temp files remain after running tests.
Solution:   Delete the right files. (Dominique Pellé, closes #8509)
2021-07-04 12:30:06 +02:00
19 changed files with 166 additions and 34 deletions

View File

@@ -1130,7 +1130,12 @@ handle_swap_exists(bufref_T *old_curbuf)
close_buffer(curwin, curbuf, DOBUF_UNLOAD, FALSE, FALSE);
if (old_curbuf == NULL || !bufref_valid(old_curbuf)
|| old_curbuf->br_buf == curbuf)
{
// Block autocommands here because curwin->w_buffer is NULL.
block_autocmds();
buf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED);
unblock_autocmds();
}
else
buf = old_curbuf->br_buf;
if (buf != NULL)

View File

@@ -2054,6 +2054,18 @@ internal_func_check_arg_types(
return OK;
}
/*
* Get the argument count for function "idx".
* "argcount" is the total argument count, "min_argcount" the non-optional
* argument count.
*/
void
internal_func_get_argcount(int idx, int *argcount, int *min_argcount)
{
*argcount = global_functions[idx].f_max_argc;
*min_argcount = global_functions[idx].f_min_argc;
}
/*
* Call the "f_retfunc" function to obtain the return type of function "idx".
* "argtypes" is the list of argument types or NULL when there are no

View File

@@ -1670,6 +1670,8 @@ ex_catch(exarg_T *eap)
for (idx = cstack->cs_idx; idx > 0; --idx)
if (cstack->cs_flags[idx] & CSF_TRY)
break;
if (cstack->cs_flags[idx] & CSF_TRY)
cstack->cs_flags[idx] |= CSF_CATCH;
if (cstack->cs_flags[idx] & CSF_FINALLY)
{
// Give up for a ":catch" after ":finally" and ignore it.
@@ -1963,8 +1965,8 @@ ex_endtry(exarg_T *eap)
* made inactive by a ":continue", ":break", ":return", or ":finish" in
* the finally clause. The latter case need not be tested since then
* anything pending has already been discarded. */
skip = did_emsg || got_int || did_throw ||
!(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
skip = did_emsg || got_int || did_throw
|| !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
{
@@ -1992,6 +1994,14 @@ ex_endtry(exarg_T *eap)
{
idx = cstack->cs_idx;
if (in_vim9script()
&& (cstack->cs_flags[idx] & (CSF_CATCH|CSF_FINALLY)) == 0)
{
// try/endtry without any catch or finally: give an error and
// continue.
eap->errmsg = _(e_missing_catch_or_finally);
}
/*
* If we stopped with the exception currently being thrown at this
* try conditional since we didn't know that it doesn't have

View File

@@ -421,7 +421,7 @@ 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_unknown INIT6(VAR_FUNC, -1, -1, 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);
EXTERN type_T t_func_number INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_number, NULL);

View File

@@ -6,6 +6,7 @@ int find_internal_func(char_u *name);
int has_internal_func(char_u *name);
char *internal_func_name(int idx);
int internal_func_check_arg_types(type_T **types, int idx, int argcount, cctx_T *cctx);
void internal_func_get_argcount(int idx, int *argcount, int *min_argcount);
type_T *internal_func_ret_type(int idx, int argcount, type_T **argtypes);
int internal_func_is_map(int idx);
int check_internal_func(int idx, int argcount);
@@ -21,7 +22,6 @@ void f_has(typval_T *argvars, typval_T *rettv);
int dynamic_feature(char_u *feature);
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
void range_list_materialize(list_T *list);
float_T vim_round(float_T f);
long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
void f_string(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */

View File

@@ -1,4 +1,4 @@
/* math.c */
/* float.c */
int string2float(char_u *text, float_T *value);
void f_abs(typval_T *argvars, typval_T *rettv);
void f_acos(typval_T *argvars, typval_T *rettv);
@@ -17,6 +17,7 @@ void f_isnan(typval_T *argvars, typval_T *rettv);
void f_log(typval_T *argvars, typval_T *rettv);
void f_log10(typval_T *argvars, typval_T *rettv);
void f_pow(typval_T *argvars, typval_T *rettv);
float_T vim_round(float_T f);
void f_round(typval_T *argvars, typval_T *rettv);
void f_sin(typval_T *argvars, typval_T *rettv);
void f_sinh(typval_T *argvars, typval_T *rettv);

View File

@@ -936,13 +936,14 @@ typedef struct {
# define CSF_TRY 0x0100 // is a ":try"
# define CSF_FINALLY 0x0200 // ":finally" has been passed
# define CSF_THROWN 0x0400 // exception thrown to this try conditional
# define CSF_CAUGHT 0x0800 // exception caught by this try conditional
# define CSF_SILENT 0x1000 // "emsg_silent" reset by ":try"
# define CSF_CATCH 0x0400 // ":catch" has been seen
# define CSF_THROWN 0x0800 // exception thrown to this try conditional
# define CSF_CAUGHT 0x1000 // exception caught by this try conditional
# define CSF_SILENT 0x2000 // "emsg_silent" reset by ":try"
// Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset
// (an ":if"), and CSF_SILENT is only used when CSF_TRY is set.
//
#define CSF_FUNC_DEF 0x2000 // a function was defined in this block
#define CSF_FUNC_DEF 0x4000 // a function was defined in this block
/*
* What's pending for being reactivated at the ":endtry" of this try

View File

@@ -975,8 +975,7 @@ func Test_debug_def_and_legacy_function()
call RunDbgCmd(buf, 'cont')
call StopVimInTerminal(buf)
call delete('Xtest1.vim')
call delete('Xtest2.vim')
call delete('XtestDebug.vim')
endfunc
func Test_debug_def_function()

View File

@@ -330,6 +330,7 @@ func Test_closure_error()
let caught_932 = 1
endtry
call assert_equal(1, caught_932)
call delete('Xscript')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1550,24 +1550,32 @@ func Test_popup_filter()
redraw
" e is consumed by the filter
let g:eaten = ''
call feedkeys('e', 'xt')
call assert_equal('e', g:eaten)
call feedkeys("\<F9>", 'xt')
call assert_equal("\<F9>", g:eaten)
" 0 is ignored by the filter
let g:ignored = ''
normal $
call assert_equal(9, getcurpos()[2])
call feedkeys('0', 'xt')
call assert_equal('0', g:ignored)
normal! l
call assert_equal(2, getcurpos()[2])
if has('win32') && has('gui_running')
echo "FIXME: this check is very flaky on MS-Windows GUI, the cursor doesn't move"
else
call assert_equal(1, getcurpos()[2])
endif
" x closes the popup
call feedkeys('x', 'xt')
call assert_equal("\<F9>", g:eaten)
call assert_equal(-1, winbufnr(winid))
unlet g:eaten
unlet g:ignored
delfunc MyPopupFilter
call popup_clear()
endfunc

View File

@@ -360,6 +360,7 @@ func Test_swap_prompt_splitwin()
let buf = RunVimInTerminal('', {'rows': 20})
call term_sendkeys(buf, ":set nomore\n")
call term_sendkeys(buf, ":set noruler\n")
call term_sendkeys(buf, ":split Xfile1\n")
call TermWait(buf)
call WaitForAssert({-> assert_match('^\[O\]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: $', term_getline(buf, 20))})
@@ -371,6 +372,21 @@ func Test_swap_prompt_splitwin()
call TermWait(buf)
call WaitForAssert({-> assert_match('^1$', term_getline(buf, 20))})
call StopVimInTerminal(buf)
" This caused Vim to crash when typing "q" at the swap file prompt.
let buf = RunVimInTerminal('-c "au bufadd * let foo_w = wincol()"', {'rows': 18})
call term_sendkeys(buf, ":e Xfile1\<CR>")
call WaitForAssert({-> assert_match('More', term_getline(buf, 18))})
call term_sendkeys(buf, " ")
call WaitForAssert({-> assert_match('^\[O\]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort:', term_getline(buf, 18))})
call term_sendkeys(buf, "q")
call TermWait(buf)
" check that Vim is still running
call term_sendkeys(buf, ":echo 'hello'\<CR>")
call WaitForAssert({-> assert_match('^hello', term_getline(buf, 18))})
call term_sendkeys(buf, ":%bwipe!\<CR>")
call StopVimInTerminal(buf)
%bwipe!
call delete('Xfile1')
endfunc
@@ -486,18 +502,18 @@ endfunc
" Test for renaming a buffer when the swap file is deleted out-of-band
func Test_missing_swap_file()
CheckUnix
new Xfile1
new Xfile2
call delete(swapname(''))
call assert_fails('file Xfile2', 'E301:')
call assert_equal('Xfile2', bufname())
call assert_true(bufexists('Xfile1'))
call assert_fails('file Xfile3', 'E301:')
call assert_equal('Xfile3', bufname())
call assert_true(bufexists('Xfile2'))
call assert_true(bufexists('Xfile3'))
%bw!
endfunc
" Test for :preserve command
func Test_preserve()
new Xfile1
new Xfile4
setlocal noswapfile
call assert_fails('preserve', 'E313:')
bw!
@@ -505,8 +521,8 @@ endfunc
" Test for the v:swapchoice variable
func Test_swapchoice()
call writefile(['aaa', 'bbb'], 'Xfile1')
edit Xfile1
call writefile(['aaa', 'bbb'], 'Xfile5')
edit Xfile5
preserve
let swapfname = swapname('')
let b = readblob(swapfname)
@@ -520,7 +536,7 @@ func Test_swapchoice()
autocmd!
autocmd SwapExists * let v:swapchoice = 'o'
augroup END
edit Xfile1
edit Xfile5
call assert_true(&readonly)
call assert_equal(['aaa', 'bbb'], getline(1, '$'))
%bw!
@@ -532,11 +548,11 @@ func Test_swapchoice()
autocmd SwapExists * let v:swapchoice = 'a'
augroup END
try
edit Xfile1
edit Xfile5
catch /^Vim:Interrupt$/
endtry
call assert_equal('', @%)
call assert_true(bufexists('Xfile1'))
call assert_true(bufexists('Xfile5'))
%bw!
call assert_true(filereadable(swapfname))
@@ -545,12 +561,12 @@ func Test_swapchoice()
autocmd!
autocmd SwapExists * let v:swapchoice = 'd'
augroup END
edit Xfile1
call assert_equal('Xfile1', @%)
edit Xfile5
call assert_equal('Xfile5', @%)
%bw!
call assert_false(filereadable(swapfname))
call delete('Xfile1')
call delete('Xfile5')
call delete(swapfname)
augroup test_swapchoice
autocmd!

View File

@@ -650,6 +650,27 @@ def Test_assignment_list()
d.dd[0] = 0
END
CheckDefExecFailure(lines, 'E1147:', 2)
lines =<< trim END
def OneArg(x: bool)
enddef
def TwoArgs(x: bool, y: bool)
enddef
var fl: list<func(bool, bool, bool)> = [OneArg, TwoArgs]
END
CheckDefExecAndScriptFailure(lines, 'E1012:', 5)
enddef
def PartFuncBool(b: bool): string
return 'done'
enddef
def Test_assignment_partial()
var lines =<< trim END
var Partial: func(): string = function(PartFuncBool, [true])
assert_equal('done', Partial())
END
CheckDefAndScriptSuccess(lines)
enddef
def Test_assignment_list_any_index()

View File

@@ -57,7 +57,7 @@ def Test_expr1_trinary()
assert_equal(function('len'), Res)
var RetOne: func(string): number = function('len')
var RetTwo: func(string): number = function('winnr')
var RetTwo: func(string): number = function('charcol')
var RetThat: func = g:atrue ? RetOne : RetTwo
assert_equal(function('len'), RetThat)

View File

@@ -1030,7 +1030,7 @@ def Test_pass_legacy_lambda_to_def_func()
lines =<< trim END
vim9script
def g:TestFunc(f: func())
def g:TestFunc(f: func)
enddef
legacy call g:TestFunc({-> 0})
delfunc g:TestFunc

View File

@@ -603,6 +603,15 @@ def Test_try_catch_throw()
CheckScriptSuccess(lines)
assert_match('E808: Number or Float required', g:caught)
unlet g:caught
# missing catch and/or finally
lines =<< trim END
vim9script
try
echo 'something'
endtry
END
CheckScriptFailure(lines, 'E1032:')
enddef
def Test_try_in_catch()

View File

@@ -1262,7 +1262,7 @@ func Test_visual_block_with_virtualedit()
" clean up
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
call delete('XTest_beval')
call delete('XTest_block')
endfunc

View File

@@ -3103,6 +3103,7 @@ call_func(
int argv_clear = 0;
int argv_base = 0;
partial_T *partial = funcexe->partial;
type_T check_type;
// Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
// even when call_func() returns FAIL.
@@ -3146,6 +3147,16 @@ call_func(
argv[i + argv_clear] = argvars_in[i];
argvars = argv;
argcount = partial->pt_argc + argcount_in;
if (funcexe->check_type != NULL)
{
// Now funcexe->check_type is missing the added arguments, make
// a copy of the type with the correction.
check_type = *funcexe->check_type;
funcexe->check_type = &check_type;
check_type.tt_argcount += partial->pt_argc;
check_type.tt_min_argcount += partial->pt_argc;
}
}
}

View File

@@ -755,6 +755,26 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3105,
/**/
3104,
/**/
3103,
/**/
3102,
/**/
3101,
/**/
3100,
/**/
3099,
/**/
3098,
/**/
3097,
/**/
3096,
/**/
3095,
/**/

View File

@@ -260,6 +260,7 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
type_T *type;
type_T *member_type = &t_any;
int argcount = 0;
int min_argcount = 0;
if (tv->v_type == VAR_NUMBER)
return &t_number;
@@ -337,8 +338,7 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
if (idx >= 0)
{
// TODO: get actual arg count and types
argcount = -1;
internal_func_get_argcount(idx, &argcount, &min_argcount);
member_type = internal_func_ret_type(idx, 0, NULL);
}
else
@@ -355,7 +355,20 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
if (ufunc->uf_func_type == NULL)
set_function_type(ufunc);
if (ufunc->uf_func_type != NULL)
{
if (tv->v_type == VAR_PARTIAL
&& tv->vval.v_partial->pt_argc > 0)
{
type = get_type_ptr(type_gap);
if (type == NULL)
return NULL;
*type = *ufunc->uf_func_type;
type->tt_argcount -= tv->vval.v_partial->pt_argc;
type->tt_min_argcount -= tv->vval.v_partial->pt_argc;
return type;
}
return ufunc->uf_func_type;
}
}
}
@@ -364,6 +377,7 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
return NULL;
type->tt_type = tv->v_type;
type->tt_argcount = argcount;
type->tt_min_argcount = min_argcount;
type->tt_member = member_type;
return type;
@@ -525,9 +539,10 @@ check_type(type_T *expected, type_T *actual, int give_msg, where_T where)
ret = check_type(expected->tt_member, actual->tt_member,
FALSE, where);
if (ret == OK && expected->tt_argcount != -1
&& actual->tt_argcount != -1
&& (actual->tt_argcount < expected->tt_min_argcount
|| actual->tt_argcount > expected->tt_argcount))
&& actual->tt_min_argcount != -1
&& (actual->tt_argcount == -1
|| (actual->tt_argcount < expected->tt_min_argcount
|| actual->tt_argcount > expected->tt_argcount)))
ret = FAIL;
if (ret == OK && expected->tt_args != NULL
&& actual->tt_args != NULL)
@@ -1032,7 +1047,10 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
}
}
else
// Use -1 for "tt_argcount" to indicate an unknown number of
// arguments.
*dest = alloc_func_type(common, -1, type_gap);
// Use the minimum of min_argcount.
(*dest)->tt_min_argcount =
type1->tt_min_argcount < type2->tt_min_argcount