0
0
mirror of https://github.com/vim/vim.git synced 2025-09-30 04:44:14 -04:00

patch 8.2.3211: Vim9: argument types are not checked at compile time

Problem:    Vim9: argument types are not checked at compile time.
Solution:   Add several more type checks. Fix type check for matchaddpos().
            (Yegappan Lakshmanan, closes #8619)
This commit is contained in:
Yegappan Lakshmanan
2021-07-24 16:16:15 +02:00
committed by Bram Moolenaar
parent dd0b287c1e
commit 7973de35ba
10 changed files with 165 additions and 22 deletions

View File

@@ -4890,9 +4890,15 @@ f_ch_info(typval_T *argvars, typval_T *rettv UNUSED)
void void
f_ch_log(typval_T *argvars, typval_T *rettv UNUSED) f_ch_log(typval_T *argvars, typval_T *rettv UNUSED)
{ {
char_u *msg = tv_get_string(&argvars[0]); char_u *msg;
channel_T *channel = NULL; channel_T *channel = NULL;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_opt_chan_or_job_arg(argvars, 1) == FAIL))
return;
msg = tv_get_string(&argvars[0]);
if (argvars[1].v_type != VAR_UNKNOWN) if (argvars[1].v_type != VAR_UNKNOWN)
channel = get_channel_arg(&argvars[1], FALSE, FALSE, 0); channel = get_channel_arg(&argvars[1], FALSE, FALSE, 0);

View File

@@ -542,7 +542,8 @@ arg_dict_any_or_string(type_T *type, argcontext_T *context)
} }
/* /*
* Check "type" which is the third argument of extend(). * Check "type" which is the third argument of extend() (number or string or
* any)
*/ */
static int static int
arg_extend3(type_T *type, argcontext_T *context) arg_extend3(type_T *type, argcontext_T *context)
@@ -557,7 +558,8 @@ arg_extend3(type_T *type, argcontext_T *context)
} }
/* /*
* Check "type" which is the second argument of remove(). * Check "type" which is the second argument of remove() (number or string or
* any)
*/ */
static int static int
arg_remove2(type_T *type, argcontext_T *context) arg_remove2(type_T *type, argcontext_T *context)
@@ -572,7 +574,8 @@ arg_remove2(type_T *type, argcontext_T *context)
} }
/* /*
* Check "type" which is the first argument of repeat(). * Check "type" which is the first argument of repeat() (string or number or
* list or any)
*/ */
static int static int
arg_repeat1(type_T *type, argcontext_T *context) arg_repeat1(type_T *type, argcontext_T *context)
@@ -588,7 +591,8 @@ arg_repeat1(type_T *type, argcontext_T *context)
} }
/* /*
* Check "type" which is the first argument of slice(). * Check "type" which is the first argument of slice() (list or blob or string
* or any)
*/ */
static int static int
arg_slice1(type_T *type, argcontext_T *context) arg_slice1(type_T *type, argcontext_T *context)
@@ -604,7 +608,8 @@ arg_slice1(type_T *type, argcontext_T *context)
} }
/* /*
* Check "type" which is the first argument of count(). * Check "type" which is the first argument of count() (string or list or dict
* or any)
*/ */
static int static int
arg_count1(type_T *type, argcontext_T *context) arg_count1(type_T *type, argcontext_T *context)
@@ -620,7 +625,8 @@ arg_count1(type_T *type, argcontext_T *context)
} }
/* /*
* Check "type" which is the first argument of cursor(). * Check "type" which is the first argument of cursor() (number or string or
* list or any)
*/ */
static int static int
arg_cursor1(type_T *type, argcontext_T *context) arg_cursor1(type_T *type, argcontext_T *context)
@@ -666,6 +672,7 @@ static argcheck_T arg2_string_list_nr[] = {arg_string, arg_list_number};
static argcheck_T arg2_string_bool[] = {arg_string, arg_bool}; static argcheck_T arg2_string_bool[] = {arg_string, arg_bool};
static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any};
static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr}; static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr};
static argcheck_T arg2_string_chan_or_job[] = {arg_string, arg_chan_or_job};
static argcheck_T arg2_list_number[] = {arg_list_number, arg_list_number}; static argcheck_T arg2_list_number[] = {arg_list_number, arg_list_number};
static argcheck_T arg2_list_number_bool[] = {arg_list_number, arg_bool}; static argcheck_T arg2_list_number_bool[] = {arg_list_number, arg_bool};
static argcheck_T arg2_list_any_string[] = {arg_list_any, arg_string}; static argcheck_T arg2_list_any_string[] = {arg_list_any, arg_string};
@@ -690,11 +697,14 @@ static argcheck_T arg2_buffer_number[] = {arg_buffer, arg_number};
static argcheck_T arg2_buffer_bool[] = {arg_buffer, arg_bool}; static argcheck_T arg2_buffer_bool[] = {arg_buffer, arg_bool};
static argcheck_T arg2_buffer_lnum[] = {arg_buffer, arg_lnum}; static argcheck_T arg2_buffer_lnum[] = {arg_buffer, arg_lnum};
static argcheck_T arg2_buffer_list_any[] = {arg_buffer, arg_list_any}; static argcheck_T arg2_buffer_list_any[] = {arg_buffer, arg_list_any};
static argcheck_T arg2_buffer_any[] = {arg_buffer, NULL};
static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
static argcheck_T arg3_number_number_dict[] = {arg_number, arg_number, arg_dict_any}; static argcheck_T arg3_number_number_dict[] = {arg_number, arg_number, arg_dict_any};
static argcheck_T arg3_number_string_string[] = {arg_number, arg_string, arg_string};
static argcheck_T arg3_number_string_any[] = {arg_number, arg_string, NULL}; static argcheck_T arg3_number_string_any[] = {arg_number, arg_string, NULL};
static argcheck_T arg3_number_string_buffer[] = {arg_number, arg_string, arg_buffer}; static argcheck_T arg3_number_string_buffer[] = {arg_number, arg_string, arg_buffer};
static argcheck_T arg3_number_any_dict[] = {arg_number, NULL, arg_dict_any};
static argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; static argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number};
static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any};
@@ -707,6 +717,7 @@ static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool};
static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum}; static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum};
static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_number}; static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_number};
static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any}; static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any};
static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, NULL};
static argcheck_T arg4_number_number_string_any[] = {arg_number, arg_number, arg_string, NULL}; static argcheck_T arg4_number_number_string_any[] = {arg_number, arg_number, arg_string, NULL};
static argcheck_T arg4_string_string_number_string[] = {arg_string, arg_string, arg_number, arg_string}; static argcheck_T arg4_string_string_number_string[] = {arg_string, arg_string, arg_number, arg_string};
static argcheck_T arg5_number[] = {arg_number, arg_number, arg_number, arg_number, arg_number}; static argcheck_T arg5_number[] = {arg_number, arg_number, arg_number, arg_number, arg_number};
@@ -726,12 +737,13 @@ static argcheck_T arg23_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_numb
static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL}; static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL};
static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool}; static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool};
static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any}; static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any};
static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_number, arg_number, arg_number, arg_dict_any}; static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any};
static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL}; static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL};
static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number}; static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number};
static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2, arg_number}; static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2, arg_number};
static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number}; static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number};
static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number, arg_number, NULL}; static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number, arg_number, NULL};
static argcheck_T arg37_searchpair[] = {arg_string, arg_string, arg_string, arg_string, NULL, arg_number, arg_number};
static argcheck_T arg3_setbufline[] = {arg_buffer, arg_lnum, arg_str_or_nr_or_list}; static argcheck_T arg3_setbufline[] = {arg_buffer, arg_lnum, arg_str_or_nr_or_list};
static argcheck_T arg2_setline[] = {arg_lnum, NULL}; static argcheck_T arg2_setline[] = {arg_lnum, NULL};
static argcheck_T arg24_setloclist[] = {arg_number, arg_list_any, arg_string, arg_dict_any}; static argcheck_T arg24_setloclist[] = {arg_number, arg_list_any, arg_string, arg_dict_any};
@@ -1146,7 +1158,7 @@ static funcentry_T global_functions[] =
ret_job, JOB_FUNC(f_ch_getjob)}, ret_job, JOB_FUNC(f_ch_getjob)},
{"ch_info", 1, 1, FEARG_1, arg1_chan_or_job, {"ch_info", 1, 1, FEARG_1, arg1_chan_or_job,
ret_dict_any, JOB_FUNC(f_ch_info)}, ret_dict_any, JOB_FUNC(f_ch_info)},
{"ch_log", 1, 2, FEARG_1, NULL, {"ch_log", 1, 2, FEARG_1, arg2_string_chan_or_job,
ret_void, JOB_FUNC(f_ch_log)}, ret_void, JOB_FUNC(f_ch_log)},
{"ch_logfile", 1, 2, FEARG_1, arg2_string, {"ch_logfile", 1, 2, FEARG_1, arg2_string,
ret_void, JOB_FUNC(f_ch_logfile)}, ret_void, JOB_FUNC(f_ch_logfile)},
@@ -1202,7 +1214,7 @@ static funcentry_T global_functions[] =
ret_float, FLOAT_FUNC(f_cosh)}, ret_float, FLOAT_FUNC(f_cosh)},
{"count", 2, 4, FEARG_1, arg24_count, {"count", 2, 4, FEARG_1, arg24_count,
ret_number, f_count}, ret_number, f_count},
{"cscope_connection",0,3, 0, NULL, {"cscope_connection",0,3, 0, arg3_number_string_string,
ret_number, f_cscope_connection}, ret_number, f_cscope_connection},
{"cursor", 1, 3, FEARG_1, arg13_cursor, {"cursor", 1, 3, FEARG_1, arg13_cursor,
ret_number, f_cursor}, ret_number, f_cursor},
@@ -1310,7 +1322,7 @@ static funcentry_T global_functions[] =
ret_list_dict_any, f_getbufinfo}, ret_list_dict_any, f_getbufinfo},
{"getbufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum, {"getbufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum,
ret_list_string, f_getbufline}, ret_list_string, f_getbufline},
{"getbufvar", 2, 3, FEARG_1, NULL, {"getbufvar", 2, 3, FEARG_1, arg3_buffer_string_any,
ret_any, f_getbufvar}, ret_any, f_getbufvar},
{"getchangelist", 0, 1, FEARG_1, arg1_buffer, {"getchangelist", 0, 1, FEARG_1, arg1_buffer,
ret_list_any, f_getchangelist}, ret_list_any, f_getchangelist},
@@ -1650,9 +1662,9 @@ static funcentry_T global_functions[] =
ret_string, f_printf}, ret_string, f_printf},
{"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer, {"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer,
ret_string, JOB_FUNC(f_prompt_getprompt)}, ret_string, JOB_FUNC(f_prompt_getprompt)},
{"prompt_setcallback", 2, 2, FEARG_1, NULL, {"prompt_setcallback", 2, 2, FEARG_1, arg2_buffer_any,
ret_void, JOB_FUNC(f_prompt_setcallback)}, ret_void, JOB_FUNC(f_prompt_setcallback)},
{"prompt_setinterrupt", 2, 2, FEARG_1, NULL, {"prompt_setinterrupt", 2, 2, FEARG_1, arg2_buffer_any,
ret_void, JOB_FUNC(f_prompt_setinterrupt)}, ret_void, JOB_FUNC(f_prompt_setinterrupt)},
{"prompt_setprompt", 2, 2, FEARG_1, arg2_buffer_string, {"prompt_setprompt", 2, 2, FEARG_1, arg2_buffer_string,
ret_void, JOB_FUNC(f_prompt_setprompt)}, ret_void, JOB_FUNC(f_prompt_setprompt)},
@@ -1780,9 +1792,9 @@ static funcentry_T global_functions[] =
ret_dict_any, f_searchcount}, ret_dict_any, f_searchcount},
{"searchdecl", 1, 3, FEARG_1, arg3_string_bool_bool, {"searchdecl", 1, 3, FEARG_1, arg3_string_bool_bool,
ret_number_bool, f_searchdecl}, ret_number_bool, f_searchdecl},
{"searchpair", 3, 7, 0, NULL, {"searchpair", 3, 7, 0, arg37_searchpair,
ret_number, f_searchpair}, ret_number, f_searchpair},
{"searchpairpos", 3, 7, 0, NULL, {"searchpairpos", 3, 7, 0, arg37_searchpair,
ret_list_number, f_searchpairpos}, ret_list_number, f_searchpairpos},
{"searchpos", 1, 5, FEARG_1, arg15_search, {"searchpos", 1, 5, FEARG_1, arg15_search,
ret_list_number, f_searchpos}, ret_list_number, f_searchpos},
@@ -1792,7 +1804,7 @@ static funcentry_T global_functions[] =
ret_string, f_serverlist}, ret_string, f_serverlist},
{"setbufline", 3, 3, FEARG_3, arg3_setbufline, {"setbufline", 3, 3, FEARG_3, arg3_setbufline,
ret_number_bool, f_setbufline}, ret_number_bool, f_setbufline},
{"setbufvar", 3, 3, FEARG_3, NULL, {"setbufvar", 3, 3, FEARG_3, arg3_buffer_string_any,
ret_void, f_setbufvar}, ret_void, f_setbufvar},
{"setcellwidths", 1, 1, FEARG_1, arg1_list_any, {"setcellwidths", 1, 1, FEARG_1, arg1_list_any,
ret_void, f_setcellwidths}, ret_void, f_setcellwidths},
@@ -1950,7 +1962,7 @@ static funcentry_T global_functions[] =
ret_string, f_swapname}, ret_string, f_swapname},
{"synID", 3, 3, 0, arg3_lnum_number_bool, {"synID", 3, 3, 0, arg3_lnum_number_bool,
ret_number, f_synID}, ret_number, f_synID},
{"synIDattr", 2, 3, FEARG_1, NULL, {"synIDattr", 2, 3, FEARG_1, arg3_number_string_string,
ret_string, f_synIDattr}, ret_string, f_synIDattr},
{"synIDtrans", 1, 1, FEARG_1, arg1_number, {"synIDtrans", 1, 1, FEARG_1, arg1_number,
ret_number, f_synIDtrans}, ret_number, f_synIDtrans},
@@ -2102,7 +2114,7 @@ static funcentry_T global_functions[] =
ret_list_dict_any, TIMER_FUNC(f_timer_info)}, ret_list_dict_any, TIMER_FUNC(f_timer_info)},
{"timer_pause", 2, 2, FEARG_1, arg2_number_bool, {"timer_pause", 2, 2, FEARG_1, arg2_number_bool,
ret_void, TIMER_FUNC(f_timer_pause)}, ret_void, TIMER_FUNC(f_timer_pause)},
{"timer_start", 2, 3, FEARG_1, NULL, {"timer_start", 2, 3, FEARG_1, arg3_number_any_dict,
ret_number, TIMER_FUNC(f_timer_start)}, ret_number, TIMER_FUNC(f_timer_start)},
{"timer_stop", 1, 1, FEARG_1, arg1_number, {"timer_stop", 1, 1, FEARG_1, arg1_number,
ret_void, TIMER_FUNC(f_timer_stop)}, ret_void, TIMER_FUNC(f_timer_stop)},
@@ -8044,6 +8056,18 @@ searchpair_cmn(typval_T *argvars, pos_T *match_pos)
long lnum_stop = 0; long lnum_stop = 0;
long time_limit = 0; long time_limit = 0;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL
|| check_for_string_arg(argvars, 2) == FAIL
|| check_for_opt_string_arg(argvars, 3) == FAIL
|| (argvars[3].v_type != VAR_UNKNOWN
&& argvars[4].v_type != VAR_UNKNOWN
&& (check_for_opt_number_arg(argvars, 5) == FAIL
|| (argvars[5].v_type != VAR_UNKNOWN
&& check_for_opt_number_arg(argvars, 6) == FAIL)))))
goto theend;
// Get the three pattern arguments: start, middle, end. Will result in an // Get the three pattern arguments: start, middle, end. Will result in an
// error if not a valid argument. // error if not a valid argument.
spat = tv_get_string_chk(&argvars[0]); spat = tv_get_string_chk(&argvars[0]);
@@ -9245,6 +9269,13 @@ f_synIDattr(typval_T *argvars UNUSED, typval_T *rettv)
char_u modebuf[NUMBUFLEN]; char_u modebuf[NUMBUFLEN];
int modec; int modec;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| (check_for_string_arg(argvars, 1) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_opt_string_arg(argvars, 2) == FAIL))))
return;
id = (int)tv_get_number(&argvars[0]); id = (int)tv_get_number(&argvars[0]);
what = tv_get_string(&argvars[1]); what = tv_get_string(&argvars[1]);
if (argvars[2].v_type != VAR_UNKNOWN) if (argvars[2].v_type != VAR_UNKNOWN)

View File

@@ -4112,6 +4112,11 @@ f_getbufvar(typval_T *argvars, typval_T *rettv)
dictitem_T *v; dictitem_T *v;
int done = FALSE; int done = FALSE;
if (in_vim9script()
&& (check_for_buffer_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL))
return;
varname = tv_get_string_chk(&argvars[1]); varname = tv_get_string_chk(&argvars[1]);
buf = tv_get_buf_from_arg(&argvars[0]); buf = tv_get_buf_from_arg(&argvars[0]);
@@ -4251,6 +4256,12 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
if (check_secure()) if (check_secure())
return; return;
if (in_vim9script()
&& (check_for_buffer_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL))
return;
varname = tv_get_string_chk(&argvars[1]); varname = tv_get_string_chk(&argvars[1]);
buf = tv_get_buf_from_arg(&argvars[0]); buf = tv_get_buf_from_arg(&argvars[0]);
varp = &argvars[2]; varp = &argvars[2];

View File

@@ -2496,6 +2496,14 @@ f_cscope_connection(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
char_u *prepend = NULL; char_u *prepend = NULL;
char_u buf[NUMBUFLEN]; char_u buf[NUMBUFLEN];
if (in_vim9script()
&& (check_for_opt_number_arg(argvars, 0) == FAIL
|| (argvars[0].v_type != VAR_UNKNOWN
&& (check_for_opt_string_arg(argvars, 1) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_opt_string_arg(argvars, 2) == FAIL)))))
return;
if (argvars[0].v_type != VAR_UNKNOWN if (argvars[0].v_type != VAR_UNKNOWN
&& argvars[1].v_type != VAR_UNKNOWN) && argvars[1].v_type != VAR_UNKNOWN)
{ {

View File

@@ -1658,6 +1658,10 @@ f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
if (check_secure()) if (check_secure())
return; return;
if (in_vim9script() && check_for_buffer_arg(argvars, 0) == FAIL)
return;
buf = tv_get_buf(&argvars[0], FALSE); buf = tv_get_buf(&argvars[0], FALSE);
if (buf == NULL) if (buf == NULL)
return; return;
@@ -1681,6 +1685,10 @@ f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv UNUSED)
if (check_secure()) if (check_secure())
return; return;
if (in_vim9script() && check_for_buffer_arg(argvars, 0) == FAIL)
return;
buf = tv_get_buf(&argvars[0], FALSE); buf = tv_get_buf(&argvars[0], FALSE);
if (buf == NULL) if (buf == NULL)
return; return;

View File

@@ -21,6 +21,7 @@ int check_for_opt_list_arg(typval_T *args, int idx);
int check_for_dict_arg(typval_T *args, int idx); int check_for_dict_arg(typval_T *args, int idx);
int check_for_opt_dict_arg(typval_T *args, int idx); int check_for_opt_dict_arg(typval_T *args, int idx);
int check_for_chan_or_job_arg(typval_T *args, int idx); int check_for_chan_or_job_arg(typval_T *args, int idx);
int check_for_opt_chan_or_job_arg(typval_T *args, int idx);
int check_for_job_arg(typval_T *args, int idx); int check_for_job_arg(typval_T *args, int idx);
int check_for_string_or_number_arg(typval_T *args, int idx); int check_for_string_or_number_arg(typval_T *args, int idx);
int check_for_buffer_arg(typval_T *args, int idx); int check_for_buffer_arg(typval_T *args, int idx);

View File

@@ -445,6 +445,15 @@ def Test_ch_info()
endif endif
enddef enddef
def Test_ch_log()
if !has('channel')
CheckFeature channel
else
CheckDefAndScriptFailure2(['ch_log(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['ch_log("a", 1)'], 'E1013: Argument 2: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 2')
endif
enddef
def Test_ch_logfile() def Test_ch_logfile()
if !has('channel') if !has('channel')
CheckFeature channel CheckFeature channel
@@ -654,6 +663,14 @@ def Test_count()
count({a: 1.1, b: 2.2, c: 1.1}, 1.1)->assert_equal(2) count({a: 1.1, b: 2.2, c: 1.1}, 1.1)->assert_equal(2)
enddef enddef
def Test_cscope_connection()
CheckFeature cscope
assert_equal(0, cscope_connection())
CheckDefAndScriptFailure2(['cscope_connection("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1')
CheckDefAndScriptFailure2(['cscope_connection(1, 2)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2')
CheckDefAndScriptFailure2(['cscope_connection(1, "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3')
enddef
def Test_cursor() def Test_cursor()
new new
setline(1, range(4)) setline(1, range(4))
@@ -1144,6 +1161,11 @@ def Test_getbufline()
CheckDefAndScriptFailure2(['getbufline("a", 2, 0z10)'], 'E1013: Argument 3: type mismatch, expected string but got blob', 'E1174: String required for argument 3') CheckDefAndScriptFailure2(['getbufline("a", 2, 0z10)'], 'E1013: Argument 3: type mismatch, expected string but got blob', 'E1174: String required for argument 3')
enddef enddef
def Test_getbufvar()
CheckDefAndScriptFailure2(['getbufvar(true, "v")'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['getbufvar(1, 2, 3)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2')
enddef
def Test_getchangelist() def Test_getchangelist()
new new
setline(1, 'some text') setline(1, 'some text')
@@ -1862,8 +1884,7 @@ enddef
def Test_matchaddpos() def Test_matchaddpos()
CheckDefAndScriptFailure2(['matchaddpos(1, [1])'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') CheckDefAndScriptFailure2(['matchaddpos(1, [1])'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['matchaddpos("a", "b")'], 'E1013: Argument 2: type mismatch, expected list<number> but got string', 'E1211: List required for argument 2') CheckDefAndScriptFailure2(['matchaddpos("a", "b")'], 'E1013: Argument 2: type mismatch, expected list<any> but got string', 'E1211: List required for argument 2')
CheckDefFailure(['matchaddpos("a", ["2"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
CheckDefAndScriptFailure2(['matchaddpos("a", [1], "c")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') CheckDefAndScriptFailure2(['matchaddpos("a", [1], "c")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3')
CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, "d")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, "d")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4')
CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, 1, [])'], 'E1013: Argument 5: type mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary required for argument 5') CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, 1, [])'], 'E1013: Argument 5: type mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary required for argument 5')
@@ -2148,6 +2169,22 @@ def Test_prompt_getprompt()
endif endif
enddef enddef
def Test_prompt_setcallback()
if !has('channel')
CheckFeature channel
else
CheckDefAndScriptFailure2(['prompt_setcallback(true, "1")'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1')
endif
enddef
def Test_prompt_setinterrupt()
if !has('channel')
CheckFeature channel
else
CheckDefAndScriptFailure2(['prompt_setinterrupt(true, "1")'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1')
endif
enddef
def Test_prompt_setprompt() def Test_prompt_setprompt()
if !has('channel') if !has('channel')
CheckFeature channel CheckFeature channel
@@ -2575,13 +2612,20 @@ def Test_searchpair()
lines =<< trim END lines =<< trim END
def TestPair() def TestPair()
echo searchpair("a", "b", "c", "d", "1", "f") echo searchpair("a", "b", "c", "d", "1", 99)
enddef enddef
defcompile defcompile
END END
CheckScriptSuccess(lines) CheckScriptSuccess(lines)
bwipe! bwipe!
CheckDefAndScriptFailure2(['searchpair(1, "b", "c")'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['searchpair("a", 2, "c")'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2')
CheckDefAndScriptFailure2(['searchpair("a", "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3')
CheckDefAndScriptFailure2(['searchpair("a", "b", "c", 4)'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4')
# BUG: Vim crashes with the following test
#CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "d", "1", "f")'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4')
#CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "d", "1", 3, "g")'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4')
enddef enddef
def Test_searchpos() def Test_searchpos()
@@ -2676,6 +2720,9 @@ def Test_setbufvar()
setbufvar('%', 'myvar', 123) setbufvar('%', 'myvar', 123)
getbufvar('%', 'myvar')->assert_equal(123) getbufvar('%', 'myvar')->assert_equal(123)
CheckDefAndScriptFailure2(['setbufvar(true, "v", 3)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['setbufvar(1, 2, 3)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2')
enddef enddef
def Test_setbufline() def Test_setbufline()
@@ -3112,6 +3159,12 @@ def Test_synID()
CheckDefAndScriptFailure2(['synID(1, 1, 2)'], 'E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3') CheckDefAndScriptFailure2(['synID(1, 1, 2)'], 'E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3')
enddef enddef
def Test_synIDattr()
CheckDefAndScriptFailure2(['synIDattr("a", "b")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1')
CheckDefAndScriptFailure2(['synIDattr(1, 2)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2')
CheckDefAndScriptFailure2(['synIDattr(1, "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3')
enddef
def Test_synIDtrans() def Test_synIDtrans()
CheckDefFailure(['synIDtrans("a")'], 'E1013: Argument 1: type mismatch, expected number but got string') CheckDefFailure(['synIDtrans("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
enddef enddef
@@ -3379,6 +3432,11 @@ def Test_timer_paused()
timer_stop(id) timer_stop(id)
enddef enddef
def Test_timer_start()
CheckDefAndScriptFailure2(['timer_start("a", "1")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1')
CheckDefAndScriptFailure2(['timer_start(1, "1", [1])'], 'E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3')
enddef
def Test_timer_stop() def Test_timer_stop()
CheckDefFailure(['timer_stop("x")'], 'E1013: Argument 1: type mismatch, expected number but got string') CheckDefFailure(['timer_stop("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
assert_equal(0, timer_stop(100)) assert_equal(0, timer_stop(100))

View File

@@ -799,7 +799,7 @@ f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED)
void void
f_timer_start(typval_T *argvars, typval_T *rettv) f_timer_start(typval_T *argvars, typval_T *rettv)
{ {
long msec = (long)tv_get_number(&argvars[0]); long msec;
timer_T *timer; timer_T *timer;
int repeat = 0; int repeat = 0;
callback_T callback; callback_T callback;
@@ -808,6 +808,13 @@ f_timer_start(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
if (check_secure()) if (check_secure())
return; return;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_opt_dict_arg(argvars, 2) == FAIL))
return;
msec = (long)tv_get_number(&argvars[0]);
if (argvars[2].v_type != VAR_UNKNOWN) if (argvars[2].v_type != VAR_UNKNOWN)
{ {
if (argvars[2].v_type != VAR_DICT if (argvars[2].v_type != VAR_DICT

View File

@@ -522,6 +522,17 @@ check_for_chan_or_job_arg(typval_T *args, int idx)
return OK; return OK;
} }
/*
* Give an error and return FAIL unless "args[idx]" is an optional channel or a
* job.
*/
int
check_for_opt_chan_or_job_arg(typval_T *args, int idx)
{
return (args[idx].v_type == VAR_UNKNOWN
|| check_for_chan_or_job_arg(args, idx) != FAIL);
}
/* /*
* Give an error and return FAIL unless "args[idx]" is a job. * Give an error and return FAIL unless "args[idx]" is a job.
*/ */

View File

@@ -755,6 +755,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 */
/**/
3211,
/**/ /**/
3210, 3210,
/**/ /**/