# HG changeset patch # User Bram Moolenaar # Date 1626346806 -7200 # Node ID acda780ffc3e83a01080b3e068444dc5713407dc # Parent 6024f64e0d2b9b406268f14f22da95758aa61a3f patch 8.2.3162: Vim9: argument types are not checked at compile time Commit: https://github.com/vim/vim/commit/1a71d31bf34b0b2b08517903826004ec6fd440e5 Author: Yegappan Lakshmanan Date: Thu Jul 15 12:49:58 2021 +0200 patch 8.2.3162: Vim9: argument types are not checked at compile time Problem: Vim9: argument types are not checked at compile time. Solution: Add more type checks. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/8560) diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -852,7 +852,7 @@ 11. Job functions *job-functions-det job_getchannel({job}) *job_getchannel()* Get the channel handle that {job} is using. To check if the job has no channel: > - if string(job_getchannel()) == 'channel fail' + if string(job_getchannel(job)) == 'channel fail' < Can also be used as a |method|: > GetJob()->job_getchannel() diff --git a/src/clientserver.c b/src/clientserver.c --- a/src/clientserver.c +++ b/src/clientserver.c @@ -887,8 +887,15 @@ f_remote_read(typval_T *argvars UNUSED, char_u *r = NULL; #ifdef FEAT_CLIENTSERVER - char_u *serverid = tv_get_string_chk(&argvars[0]); + char_u *serverid; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 1) == FAIL))) + return; + + serverid = tv_get_string_chk(&argvars[0]); if (serverid != NULL && !check_restricted() && !check_secure()) { int timeout = 0; diff --git a/src/cmdhist.c b/src/cmdhist.c --- a/src/cmdhist.c +++ b/src/cmdhist.c @@ -597,6 +597,12 @@ f_histget(typval_T *argvars UNUSED, typv int idx; char_u *str; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 1) == FAIL))) + return; + str = tv_get_string_chk(&argvars[0]); // NULL on type error if (str == NULL) rettv->vval.v_string = NULL; diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -500,3 +500,5 @@ EXTERN char e_complete_used_without_narg INIT(= N_("E1208: -complete used without -nargs")); EXTERN char e_invalid_value_for_line_number_str[] INIT(= N_("E1209: Invalid value for a line number: \"%s\"")); +EXTERN char e_number_required_for_argument_nr[] + INIT(= N_("E1210: Number required for argument %d")); diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -255,6 +255,15 @@ arg_dict_any(type_T *type, argcontext_T } /* + * Check "type" is a list of 'any'. + */ + static int +arg_list_any(type_T *type, argcontext_T *context) +{ + return check_arg_type(&t_list_any, type, context); +} + +/* * Check "type" is a list of numbers. */ static int @@ -287,9 +296,6 @@ arg_string(type_T *type, argcontext_T *c static int arg_bool(type_T *type, argcontext_T *context) { - if (type->tt_type == VAR_ANY - || type->tt_type == VAR_NUMBER || type->tt_type == VAR_BOOL) - return OK; return check_arg_type(&t_bool, type, context); } @@ -353,7 +359,7 @@ arg_string_or_list_any(type_T *type, arg } /* - * Check "type" is a list or a dict. + * Check "type" is a list of 'any' or a dict of 'any'. */ static int arg_list_or_dict(type_T *type, argcontext_T *context) @@ -366,12 +372,22 @@ arg_list_or_dict(type_T *type, argcontex } /* + * Check "type" is a job. + */ + static int +arg_job(type_T *type, argcontext_T *context) +{ + return check_arg_type(&t_job, type, context); +} + +/* * Check "type" is a channel or a job. */ static int arg_chan_or_job(type_T *type, argcontext_T *context) { - if (type->tt_type == VAR_CHANNEL || type->tt_type == VAR_JOB) + if (type->tt_type == VAR_ANY || + type->tt_type == VAR_CHANNEL || type->tt_type == VAR_JOB) return OK; arg_type_mismatch(&t_channel, type, context->arg_idx + 1); return FAIL; @@ -459,38 +475,47 @@ arg_extend3(type_T *type, argcontext_T * /* * Lists of functions that check the argument types of a builtin function. */ -argcheck_T arg1_string[] = {arg_string}; -argcheck_T arg1_number[] = {arg_number}; -argcheck_T arg1_dict[] = {arg_dict_any}; -argcheck_T arg1_list_nr[] = {arg_list_number}; -argcheck_T arg1_list_string[] = {arg_list_string}; -argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; -argcheck_T arg1_string_or_nr[] = {arg_string_or_nr}; -argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any}; -argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string}; -argcheck_T arg1_list_or_blob[] = {arg_list_or_blob}; -argcheck_T arg1_chan_or_job[] = {arg_chan_or_job}; -argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; -argcheck_T arg2_number[] = {arg_number, arg_number}; -argcheck_T arg2_string[] = {arg_string, arg_string}; -argcheck_T arg2_list_nr[] = {arg_list_number, arg_list_number}; -argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string}; -argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; -argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; -argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; -argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; -argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; -argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; -argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; -argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; -argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; -argcheck_T arg2_execute[] = {arg_string_or_list_string, arg_string}; -argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string}; -argcheck_T arg2_setline[] = {arg_string_or_nr, arg_string_or_list_any}; -argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_string_or_list_any}; -argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; -argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3}; -argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; +static argcheck_T arg1_string[] = {arg_string}; +static argcheck_T arg1_number[] = {arg_number}; +static argcheck_T arg1_bool[] = {arg_bool}; +static argcheck_T arg1_dict_any[] = {arg_dict_any}; +static argcheck_T arg1_job[] = {arg_job}; +static argcheck_T arg1_list_any[] = {arg_list_any}; +static argcheck_T arg1_list_nr[] = {arg_list_number}; +static argcheck_T arg1_list_string[] = {arg_list_string}; +static argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; +static argcheck_T arg1_string_or_nr[] = {arg_string_or_nr}; +static argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any}; +static argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string}; +static argcheck_T arg1_list_or_blob[] = {arg_list_or_blob}; +static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict}; +static argcheck_T arg1_chan_or_job[] = {arg_chan_or_job}; +static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; +static argcheck_T arg2_number[] = {arg_number, arg_number}; +static argcheck_T arg2_string[] = {arg_string, arg_string}; +static argcheck_T arg2_list_nr[] = {arg_list_number, arg_list_number}; +static argcheck_T arg2_nr_string[] = {arg_number, arg_string}; +static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string}; +static argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; +static argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; +static argcheck_T arg2_string_nr[] = {arg_string, arg_number}; +//static argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; +static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; +static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; +static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any}; +static argcheck_T arg2_nr_dict_any[] = {arg_number, arg_dict_any}; +//static argcheck_T arg2_string_number[] = {arg_string, arg_number}; +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_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 arg2_execute[] = {arg_string_or_list_string, arg_string}; +static argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string}; +static argcheck_T arg2_setline[] = {arg_string_or_nr, NULL}; +static argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_str_or_nr_or_list}; +static argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; +static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3}; +static argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; /* * Functions that return the return type of a builtin function. @@ -762,9 +787,9 @@ static funcentry_T global_functions[] = ret_first_arg, f_add}, {"and", 2, 2, FEARG_1, arg2_number, ret_number, f_and}, - {"append", 2, 2, FEARG_2, NULL, + {"append", 2, 2, FEARG_2, arg2_setline, ret_number_bool, f_append}, - {"appendbufline", 3, 3, FEARG_3, NULL, + {"appendbufline", 3, 3, FEARG_3, arg3_setbufline, ret_number_bool, f_appendbufline}, {"argc", 0, 1, 0, arg1_number, ret_number, f_argc}, @@ -776,7 +801,7 @@ static funcentry_T global_functions[] = ret_argv, f_argv}, {"asin", 1, 1, FEARG_1, arg1_float_or_nr, ret_float, FLOAT_FUNC(f_asin)}, - {"assert_beeps", 1, 2, FEARG_1, NULL, + {"assert_beeps", 1, 1, FEARG_1, arg1_string, ret_number_bool, f_assert_beeps}, {"assert_equal", 2, 3, FEARG_2, NULL, ret_number_bool, f_assert_equal}, @@ -792,7 +817,7 @@ static funcentry_T global_functions[] = ret_number_bool, f_assert_inrange}, {"assert_match", 2, 3, FEARG_2, arg3_string, ret_number_bool, f_assert_match}, - {"assert_nobeep", 1, 2, FEARG_1, NULL, + {"assert_nobeep", 1, 1, FEARG_1, arg1_string, ret_number_bool, f_assert_nobeep}, {"assert_notequal", 2, 3, FEARG_2, NULL, ret_number_bool, f_assert_notequal}, @@ -860,9 +885,9 @@ static funcentry_T global_functions[] = ret_number, f_bufwinnr}, {"byte2line", 1, 1, FEARG_1, arg1_number, ret_number, f_byte2line}, - {"byteidx", 2, 2, FEARG_1, NULL, + {"byteidx", 2, 2, FEARG_1, arg2_string_nr, ret_number, f_byteidx}, - {"byteidxcomp", 2, 2, FEARG_1, NULL, + {"byteidxcomp", 2, 2, FEARG_1, arg2_string_nr, ret_number, f_byteidxcomp}, {"call", 2, 3, FEARG_1, NULL, ret_any, f_call}, @@ -880,7 +905,7 @@ static funcentry_T global_functions[] = ret_any, JOB_FUNC(f_ch_evalraw)}, {"ch_getbufnr", 2, 2, FEARG_1, NULL, ret_number, JOB_FUNC(f_ch_getbufnr)}, - {"ch_getjob", 1, 1, FEARG_1, NULL, + {"ch_getjob", 1, 1, FEARG_1, arg1_chan_or_job, ret_job, JOB_FUNC(f_ch_getjob)}, {"ch_info", 1, 1, FEARG_1, arg1_chan_or_job, ret_dict_any, JOB_FUNC(f_ch_info)}, @@ -890,19 +915,19 @@ static funcentry_T global_functions[] = ret_void, JOB_FUNC(f_ch_logfile)}, {"ch_open", 1, 2, FEARG_1, arg2_string_dict, ret_channel, JOB_FUNC(f_ch_open)}, - {"ch_read", 1, 2, FEARG_1, NULL, + {"ch_read", 1, 2, FEARG_1, arg2_chan_or_job_dict, ret_string, JOB_FUNC(f_ch_read)}, - {"ch_readblob", 1, 2, FEARG_1, NULL, + {"ch_readblob", 1, 2, FEARG_1, arg2_chan_or_job_dict, ret_blob, JOB_FUNC(f_ch_readblob)}, - {"ch_readraw", 1, 2, FEARG_1, NULL, + {"ch_readraw", 1, 2, FEARG_1, arg2_chan_or_job_dict, ret_string, JOB_FUNC(f_ch_readraw)}, {"ch_sendexpr", 2, 3, FEARG_1, NULL, ret_void, JOB_FUNC(f_ch_sendexpr)}, {"ch_sendraw", 2, 3, FEARG_1, NULL, ret_void, JOB_FUNC(f_ch_sendraw)}, - {"ch_setoptions", 2, 2, FEARG_1, NULL, + {"ch_setoptions", 2, 2, FEARG_1, arg2_chan_or_job_dict, ret_void, JOB_FUNC(f_ch_setoptions)}, - {"ch_status", 1, 2, FEARG_1, NULL, + {"ch_status", 1, 2, FEARG_1, arg2_chan_or_job_dict, ret_string, JOB_FUNC(f_ch_status)}, {"changenr", 0, 0, 0, NULL, ret_number, f_changenr}, @@ -964,7 +989,7 @@ static funcentry_T global_functions[] = ret_number, f_diff_filler}, {"diff_hlID", 2, 2, FEARG_1, NULL, ret_number, f_diff_hlID}, - {"echoraw", 1, 1, FEARG_1, NULL, + {"echoraw", 1, 1, FEARG_1, arg1_string, ret_void, f_echoraw}, {"empty", 1, 1, FEARG_1, NULL, ret_number_bool, f_empty}, @@ -1040,7 +1065,7 @@ static funcentry_T global_functions[] = ret_func_any, f_funcref}, {"function", 1, 3, FEARG_1, NULL, ret_f_function, f_function}, - {"garbagecollect", 0, 1, 0, NULL, + {"garbagecollect", 0, 1, 0, arg1_bool, ret_void, f_garbagecollect}, {"get", 2, 3, FEARG_1, NULL, ret_any, f_get}, @@ -1052,15 +1077,15 @@ static funcentry_T global_functions[] = ret_any, f_getbufvar}, {"getchangelist", 0, 1, FEARG_1, arg1_string_or_nr, ret_list_any, f_getchangelist}, - {"getchar", 0, 1, 0, NULL, + {"getchar", 0, 1, 0, arg1_bool, ret_any, f_getchar}, {"getcharmod", 0, 0, 0, NULL, ret_number, f_getcharmod}, - {"getcharpos", 1, 1, FEARG_1, NULL, + {"getcharpos", 1, 1, FEARG_1, arg1_string, ret_list_number, f_getcharpos}, {"getcharsearch", 0, 0, 0, NULL, ret_dict_any, f_getcharsearch}, - {"getcharstr", 0, 1, 0, NULL, + {"getcharstr", 0, 1, 0, arg1_bool, ret_string, f_getcharstr}, {"getcmdline", 0, 0, 0, NULL, ret_string, f_getcmdline}, @@ -1096,7 +1121,7 @@ static funcentry_T global_functions[] = ret_list_any, f_getjumplist}, {"getline", 1, 2, FEARG_1, NULL, ret_f_getline, f_getline}, - {"getloclist", 1, 2, 0, NULL, + {"getloclist", 1, 2, 0, arg2_nr_dict_any, ret_list_or_dict_1, f_getloclist}, {"getmarklist", 0, 1, FEARG_1, arg1_string_or_nr, ret_list_dict_any, f_getmarklist}, @@ -1108,7 +1133,7 @@ static funcentry_T global_functions[] = ret_number, f_getpid}, {"getpos", 1, 1, FEARG_1, arg1_string, ret_list_number, f_getpos}, - {"getqflist", 0, 1, 0, arg1_dict, + {"getqflist", 0, 1, 0, arg1_dict_any, ret_list_or_dict_0, f_getqflist}, {"getreg", 0, 3, FEARG_1, NULL, ret_getreg, f_getreg}, @@ -1158,7 +1183,7 @@ static funcentry_T global_functions[] = ret_number_bool, f_histadd}, {"histdel", 1, 2, FEARG_1, NULL, ret_number_bool, f_histdel}, - {"histget", 1, 2, FEARG_1, NULL, + {"histget", 1, 2, FEARG_1, arg2_string_nr, ret_string, f_histget}, {"histnr", 1, 1, FEARG_1, arg1_string, ret_number, f_histnr}, @@ -1196,21 +1221,21 @@ static funcentry_T global_functions[] = ret_number_bool, f_isdirectory}, {"isinf", 1, 1, FEARG_1, arg1_float_or_nr, ret_number, MATH_FUNC(f_isinf)}, - {"islocked", 1, 1, FEARG_1, NULL, + {"islocked", 1, 1, FEARG_1, arg1_string, ret_number_bool, f_islocked}, {"isnan", 1, 1, FEARG_1, arg1_float_or_nr, ret_number_bool, MATH_FUNC(f_isnan)}, - {"items", 1, 1, FEARG_1, arg1_dict, + {"items", 1, 1, FEARG_1, arg1_dict_any, ret_list_items, f_items}, - {"job_getchannel", 1, 1, FEARG_1, NULL, + {"job_getchannel", 1, 1, FEARG_1, arg1_job, ret_channel, JOB_FUNC(f_job_getchannel)}, - {"job_info", 0, 1, FEARG_1, NULL, + {"job_info", 0, 1, FEARG_1, arg1_job, ret_job_info, JOB_FUNC(f_job_info)}, {"job_setoptions", 2, 2, FEARG_1, NULL, ret_void, JOB_FUNC(f_job_setoptions)}, {"job_start", 1, 2, FEARG_1, NULL, ret_job, JOB_FUNC(f_job_start)}, - {"job_status", 1, 1, FEARG_1, NULL, + {"job_status", 1, 1, FEARG_1, arg1_job, ret_string, JOB_FUNC(f_job_status)}, {"job_stop", 1, 2, FEARG_1, NULL, ret_number_bool, JOB_FUNC(f_job_stop)}, @@ -1224,7 +1249,7 @@ static funcentry_T global_functions[] = ret_any, f_json_decode}, {"json_encode", 1, 1, FEARG_1, NULL, ret_string, f_json_encode}, - {"keys", 1, 1, FEARG_1, arg1_dict, + {"keys", 1, 1, FEARG_1, arg1_dict_any, ret_list_string, f_keys}, {"last_buffer_nr", 0, 0, 0, arg1_string_or_nr, // obsolete ret_number, f_last_buffer_nr}, @@ -1234,7 +1259,7 @@ static funcentry_T global_functions[] = ret_string, f_libcall}, {"libcallnr", 3, 3, FEARG_3, NULL, ret_number, f_libcallnr}, - {"line", 1, 2, FEARG_1, NULL, + {"line", 1, 2, FEARG_1, arg2_string_nr, ret_number, f_line}, {"line2byte", 1, 1, FEARG_1, arg1_string_or_nr, ret_number, f_line2byte}, @@ -1294,7 +1319,7 @@ static funcentry_T global_functions[] = ret_string, f_matchstr}, {"matchstrpos", 2, 4, FEARG_1, NULL, ret_list_any, f_matchstrpos}, - {"max", 1, 1, FEARG_1, NULL, + {"max", 1, 1, FEARG_1, arg1_list_or_dict, ret_number, f_max}, {"menu_info", 1, 2, FEARG_1, arg2_string, ret_dict_any, @@ -1304,13 +1329,13 @@ static funcentry_T global_functions[] = NULL #endif }, - {"min", 1, 1, FEARG_1, NULL, + {"min", 1, 1, FEARG_1, arg1_list_or_dict, ret_number, f_min}, {"mkdir", 1, 3, FEARG_1, arg3_string_string_nr, ret_number_bool, f_mkdir}, - {"mode", 0, 1, FEARG_1, NULL, + {"mode", 0, 1, FEARG_1, arg1_bool, ret_string, f_mode}, - {"mzeval", 1, 1, FEARG_1, NULL, + {"mzeval", 1, 1, FEARG_1, arg1_string, ret_any, #ifdef FEAT_MZSCHEME f_mzeval @@ -1324,9 +1349,9 @@ static funcentry_T global_functions[] = ret_string, f_nr2char}, {"or", 2, 2, FEARG_1, arg2_number, ret_number, f_or}, - {"pathshorten", 1, 2, FEARG_1, NULL, + {"pathshorten", 1, 2, FEARG_1, arg2_string_nr, ret_string, f_pathshorten}, - {"perleval", 1, 1, FEARG_1, NULL, + {"perleval", 1, 1, FEARG_1, arg1_string, ret_any, #ifdef FEAT_PERL f_perleval @@ -1338,7 +1363,7 @@ static funcentry_T global_functions[] = ret_number, PROP_FUNC(f_popup_atcursor)}, {"popup_beval", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_beval)}, - {"popup_clear", 0, 1, 0, NULL, + {"popup_clear", 0, 1, 0, arg1_bool, ret_void, PROP_FUNC(f_popup_clear)}, {"popup_close", 1, 2, FEARG_1, NULL, ret_void, PROP_FUNC(f_popup_close)}, @@ -1346,19 +1371,19 @@ static funcentry_T global_functions[] = ret_number, PROP_FUNC(f_popup_create)}, {"popup_dialog", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_dialog)}, - {"popup_filter_menu", 2, 2, 0, NULL, + {"popup_filter_menu", 2, 2, 0, arg2_nr_string, ret_bool, PROP_FUNC(f_popup_filter_menu)}, - {"popup_filter_yesno", 2, 2, 0, NULL, + {"popup_filter_yesno", 2, 2, 0, arg2_nr_string, ret_bool, PROP_FUNC(f_popup_filter_yesno)}, {"popup_findinfo", 0, 0, 0, NULL, ret_number, PROP_FUNC(f_popup_findinfo)}, {"popup_findpreview", 0, 0, 0, NULL, ret_number, PROP_FUNC(f_popup_findpreview)}, - {"popup_getoptions", 1, 1, FEARG_1, NULL, + {"popup_getoptions", 1, 1, FEARG_1, arg1_number, ret_dict_any, PROP_FUNC(f_popup_getoptions)}, - {"popup_getpos", 1, 1, FEARG_1, NULL, + {"popup_getpos", 1, 1, FEARG_1, arg1_number, ret_dict_any, PROP_FUNC(f_popup_getpos)}, - {"popup_hide", 1, 1, FEARG_1, NULL, + {"popup_hide", 1, 1, FEARG_1, arg1_number, ret_void, PROP_FUNC(f_popup_hide)}, {"popup_list", 0, 0, 0, NULL, ret_list_number, PROP_FUNC(f_popup_list)}, @@ -1366,15 +1391,15 @@ static funcentry_T global_functions[] = ret_number, PROP_FUNC(f_popup_locate)}, {"popup_menu", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_menu)}, - {"popup_move", 2, 2, FEARG_1, NULL, + {"popup_move", 2, 2, FEARG_1, arg2_nr_dict_any, ret_void, PROP_FUNC(f_popup_move)}, {"popup_notification", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_notification)}, - {"popup_setoptions", 2, 2, FEARG_1, NULL, + {"popup_setoptions", 2, 2, FEARG_1, arg2_nr_dict_any, ret_void, PROP_FUNC(f_popup_setoptions)}, {"popup_settext", 2, 2, FEARG_1, NULL, ret_void, PROP_FUNC(f_popup_settext)}, - {"popup_show", 1, 1, FEARG_1, NULL, + {"popup_show", 1, 1, FEARG_1, arg1_number, ret_void, PROP_FUNC(f_popup_show)}, {"pow", 2, 2, FEARG_1, arg2_float_or_nr, ret_float, FLOAT_FUNC(f_pow)}, @@ -1396,7 +1421,7 @@ static funcentry_T global_functions[] = ret_void, PROP_FUNC(f_prop_clear)}, {"prop_find", 1, 2, FEARG_1, arg2_dict_string, ret_dict_any, PROP_FUNC(f_prop_find)}, - {"prop_list", 1, 2, FEARG_1, NULL, + {"prop_list", 1, 2, FEARG_1, arg2_nr_dict_any, ret_list_dict_any, PROP_FUNC(f_prop_list)}, {"prop_remove", 1, 3, FEARG_1, NULL, ret_number, PROP_FUNC(f_prop_remove)}, @@ -1408,13 +1433,13 @@ static funcentry_T global_functions[] = ret_void, PROP_FUNC(f_prop_type_delete)}, {"prop_type_get", 1, 2, FEARG_1, arg2_string_dict, ret_dict_any, PROP_FUNC(f_prop_type_get)}, - {"prop_type_list", 0, 1, FEARG_1, NULL, + {"prop_type_list", 0, 1, FEARG_1, arg1_dict_any, ret_list_string, PROP_FUNC(f_prop_type_list)}, {"pum_getpos", 0, 0, 0, NULL, ret_dict_number, f_pum_getpos}, {"pumvisible", 0, 0, 0, NULL, ret_number_bool, f_pumvisible}, - {"py3eval", 1, 1, FEARG_1, NULL, + {"py3eval", 1, 1, FEARG_1, arg1_string, ret_any, #ifdef FEAT_PYTHON3 f_py3eval @@ -1422,7 +1447,7 @@ static funcentry_T global_functions[] = NULL #endif }, - {"pyeval", 1, 1, FEARG_1, NULL, + {"pyeval", 1, 1, FEARG_1, arg1_string, ret_any, #ifdef FEAT_PYTHON f_pyeval @@ -1430,7 +1455,7 @@ static funcentry_T global_functions[] = NULL #endif }, - {"pyxeval", 1, 1, FEARG_1, NULL, + {"pyxeval", 1, 1, FEARG_1, arg1_string, ret_any, #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) f_pyxeval @@ -1468,7 +1493,7 @@ static funcentry_T global_functions[] = ret_string, f_remote_foreground}, {"remote_peek", 1, 2, FEARG_1, arg2_string, ret_number, f_remote_peek}, - {"remote_read", 1, 2, FEARG_1, NULL, + {"remote_read", 1, 2, FEARG_1, arg2_string_nr, ret_string, f_remote_read}, {"remote_send", 2, 3, FEARG_1, NULL, ret_string, f_remote_send}, @@ -1486,7 +1511,7 @@ static funcentry_T global_functions[] = ret_first_arg, f_reverse}, {"round", 1, 1, FEARG_1, arg1_float_or_nr, ret_float, FLOAT_FUNC(f_round)}, - {"rubyeval", 1, 1, FEARG_1, NULL, + {"rubyeval", 1, 1, FEARG_1, arg1_string, ret_any, #ifdef FEAT_RUBY f_rubyeval @@ -1510,7 +1535,7 @@ static funcentry_T global_functions[] = ret_string, f_screenstring}, {"search", 1, 5, FEARG_1, NULL, ret_number, f_search}, - {"searchcount", 0, 1, FEARG_1, arg1_dict, + {"searchcount", 0, 1, FEARG_1, arg1_dict_any, ret_dict_any, f_searchcount}, {"searchdecl", 1, 3, FEARG_1, NULL, ret_number_bool, f_searchdecl}, @@ -1524,15 +1549,15 @@ static funcentry_T global_functions[] = ret_number_bool, f_server2client}, {"serverlist", 0, 0, 0, NULL, ret_string, f_serverlist}, - {"setbufline", 3, 3, FEARG_3, NULL, + {"setbufline", 3, 3, FEARG_3, arg3_setbufline, ret_number_bool, f_setbufline}, {"setbufvar", 3, 3, FEARG_3, NULL, ret_void, f_setbufvar}, - {"setcellwidths", 1, 1, FEARG_1, NULL, + {"setcellwidths", 1, 1, FEARG_1, arg1_list_any, ret_void, f_setcellwidths}, {"setcharpos", 2, 2, FEARG_2, NULL, ret_number_bool, f_setcharpos}, - {"setcharsearch", 1, 1, FEARG_1, arg1_dict, + {"setcharsearch", 1, 1, FEARG_1, arg1_dict_any, ret_void, f_setcharsearch}, {"setcmdpos", 1, 1, FEARG_1, arg1_number, ret_number_bool, f_setcmdpos}, @@ -1542,7 +1567,7 @@ static funcentry_T global_functions[] = ret_void, f_setenv}, {"setfperm", 2, 2, FEARG_1, arg2_string, ret_number_bool, f_setfperm}, - {"setline", 2, 2, FEARG_2, NULL, + {"setline", 2, 2, FEARG_2, arg2_setline, ret_number_bool, f_setline}, {"setloclist", 2, 4, FEARG_2, NULL, ret_number_bool, f_setloclist}, @@ -1576,7 +1601,7 @@ static funcentry_T global_functions[] = ret_number, f_shiftwidth}, {"sign_define", 1, 2, FEARG_1, arg2_string_or_list_dict, ret_any, SIGN_FUNC(f_sign_define)}, - {"sign_getdefined", 0, 1, FEARG_1, NULL, + {"sign_getdefined", 0, 1, FEARG_1, arg1_string, ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)}, {"sign_getplaced", 0, 2, FEARG_1, NULL, ret_list_dict_any, SIGN_FUNC(f_sign_getplaced)}, @@ -1584,13 +1609,13 @@ static funcentry_T global_functions[] = ret_number, SIGN_FUNC(f_sign_jump)}, {"sign_place", 4, 5, FEARG_1, NULL, ret_number, SIGN_FUNC(f_sign_place)}, - {"sign_placelist", 1, 1, FEARG_1, NULL, + {"sign_placelist", 1, 1, FEARG_1, arg1_list_any, ret_list_number, SIGN_FUNC(f_sign_placelist)}, {"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list_string, ret_number_bool, SIGN_FUNC(f_sign_undefine)}, {"sign_unplace", 1, 2, FEARG_1, arg2_string_dict, ret_number_bool, SIGN_FUNC(f_sign_unplace)}, - {"sign_unplacelist", 1, 2, FEARG_1, NULL, + {"sign_unplacelist", 1, 2, FEARG_1, arg1_list_any, ret_list_number, SIGN_FUNC(f_sign_unplacelist)}, {"simplify", 1, 1, FEARG_1, arg1_string, ret_string, f_simplify}, @@ -1630,15 +1655,15 @@ static funcentry_T global_functions[] = ret_list_number, f_str2list}, {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_str2nr}, - {"strcharlen", 1, 1, FEARG_1, NULL, + {"strcharlen", 1, 1, FEARG_1, arg1_string_or_nr, ret_number, f_strcharlen}, {"strcharpart", 2, 4, FEARG_1, NULL, ret_string, f_strcharpart}, {"strchars", 1, 2, FEARG_1, NULL, ret_number, f_strchars}, - {"strdisplaywidth", 1, 2, FEARG_1, NULL, + {"strdisplaywidth", 1, 2, FEARG_1, arg2_string_nr, ret_number, f_strdisplaywidth}, - {"strftime", 1, 2, FEARG_1, NULL, + {"strftime", 1, 2, FEARG_1, arg2_string_nr, ret_string, #ifdef HAVE_STRFTIME f_strftime @@ -1646,7 +1671,7 @@ static funcentry_T global_functions[] = NULL #endif }, - {"strgetchar", 2, 2, FEARG_1, NULL, + {"strgetchar", 2, 2, FEARG_1, arg2_string_nr, ret_number, f_strgetchar}, {"stridx", 2, 3, FEARG_1, arg3_string_string_nr, ret_number, f_stridx}, @@ -1696,7 +1721,7 @@ static funcentry_T global_functions[] = ret_list_number, f_tabpagebuflist}, {"tabpagenr", 0, 1, 0, arg1_string, ret_number, f_tabpagenr}, - {"tabpagewinnr", 1, 2, FEARG_1, NULL, + {"tabpagewinnr", 1, 2, FEARG_1, arg2_nr_string, ret_number, f_tabpagewinnr}, {"tagfiles", 0, 0, 0, NULL, ret_list_string, f_tagfiles}, @@ -1724,7 +1749,7 @@ static funcentry_T global_functions[] = NULL #endif }, - {"term_getattr", 2, 2, FEARG_1, NULL, + {"term_getattr", 2, 2, FEARG_1, arg2_nr_string, ret_number, TERM_FUNC(f_term_getattr)}, {"term_getcursor", 1, 1, FEARG_1, arg1_string_or_nr, ret_list_any, TERM_FUNC(f_term_getcursor)}, @@ -1806,7 +1831,7 @@ static funcentry_T global_functions[] = ret_string, f_test_null_string}, {"test_option_not_set", 1, 1, FEARG_1, arg1_string, ret_void, f_test_option_not_set}, - {"test_override", 2, 2, FEARG_2, NULL, + {"test_override", 2, 2, FEARG_2, arg2_string_nr, ret_void, f_test_override}, {"test_refcount", 1, 1, FEARG_1, NULL, ret_number, f_test_refcount}, @@ -1858,11 +1883,11 @@ static funcentry_T global_functions[] = ret_dict_any, f_undotree}, {"uniq", 1, 3, FEARG_1, NULL, ret_list_any, f_uniq}, - {"values", 1, 1, FEARG_1, arg1_dict, + {"values", 1, 1, FEARG_1, arg1_dict_any, ret_list_any, f_values}, {"virtcol", 1, 1, FEARG_1, arg1_string_or_list_any, ret_number, f_virtcol}, - {"visualmode", 0, 1, 0, NULL, + {"visualmode", 0, 1, 0, arg1_bool, ret_string, f_visualmode}, {"wildmenumode", 0, 0, 0, NULL, ret_number, f_wildmenumode}, @@ -1900,7 +1925,7 @@ static funcentry_T global_functions[] = ret_number, f_winnr}, {"winrestcmd", 0, 0, 0, NULL, ret_string, f_winrestcmd}, - {"winrestview", 1, 1, FEARG_1, arg1_dict, + {"winrestview", 1, 1, FEARG_1, arg1_dict_any, ret_void, f_winrestview}, {"winsaveview", 0, 0, 0, NULL, ret_dict_number, f_winsaveview}, @@ -2763,8 +2788,12 @@ f_did_filetype(typval_T *argvars UNUSED, static void f_echoraw(typval_T *argvars, typval_T *rettv UNUSED) { - char_u *str = tv_get_string_chk(&argvars[0]); - + char_u *str; + + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; + + str = tv_get_string_chk(&argvars[0]); if (str != NULL && *str != NUL) { out_str(str); @@ -5956,6 +5985,10 @@ f_islocked(typval_T *argvars, typval_T * dictitem_T *di; rettv->vval.v_number = -1; + + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; + end = get_lval(tv_get_string(&argvars[0]), NULL, &lv, FALSE, FALSE, GLV_NO_AUTOLOAD | GLV_READ_ONLY, FNE_CHECK_START); if (end != NULL && lv.ll_name != NULL) @@ -6122,6 +6155,12 @@ f_line(typval_T *argvars, typval_T *rett win_T *save_curwin; tabpage_T *save_curtab; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 1) == FAIL))) + return; + if (argvars[1].v_type != VAR_UNKNOWN) { // use window specified in the second argument diff --git a/src/evalwindow.c b/src/evalwindow.c --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -653,6 +653,12 @@ f_tabpagewinnr(typval_T *argvars UNUSED, int nr = 1; tabpage_T *tp; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_string_arg(argvars, 1) == FAIL))) + return; + tp = find_tabpage((int)tv_get_number(&argvars[0])); if (tp == NULL) nr = 0; diff --git a/src/filepath.c b/src/filepath.c --- a/src/filepath.c +++ b/src/filepath.c @@ -1447,6 +1447,12 @@ f_pathshorten(typval_T *argvars, typval_ char_u *p; int trim_len = 1; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 1) == FAIL))) + return; + if (argvars[1].v_type != VAR_UNKNOWN) { trim_len = (int)tv_get_number(&argvars[1]); diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -1698,6 +1698,7 @@ EXTERN char e_cannot_mod[] INIT(= N_("E9 EXTERN char e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%s\"")); EXTERN char e_readonlysbx[] INIT(= N_("E794: Cannot set variable in the sandbox: \"%s\"")); EXTERN char e_stringreq[] INIT(= N_("E928: String required")); +EXTERN char e_numberreq[] INIT(= N_("E889: Number required")); EXTERN char e_emptykey[] INIT(= N_("E713: Cannot use empty key for Dictionary")); EXTERN char e_dictreq[] INIT(= N_("E715: Dictionary required")); EXTERN char e_listidx[] INIT(= N_("E684: list index out of range: %ld")); diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -2359,13 +2359,21 @@ filter_handle_drag(win_T *wp, int c, typ void f_popup_filter_menu(typval_T *argvars, typval_T *rettv) { - int id = tv_get_number(&argvars[0]); - win_T *wp = win_id2wp(id); - char_u *key = tv_get_string(&argvars[1]); + int id; + win_T *wp; + char_u *key; typval_T res; int c; linenr_T old_lnum; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL)) + return; + + id = tv_get_number(&argvars[0]); + wp = win_id2wp(id); + key = tv_get_string(&argvars[1]); // If the popup has been closed do not consume the key. if (wp == NULL) return; @@ -2416,12 +2424,20 @@ f_popup_filter_menu(typval_T *argvars, t void f_popup_filter_yesno(typval_T *argvars, typval_T *rettv) { - int id = tv_get_number(&argvars[0]); - win_T *wp = win_id2wp(id); - char_u *key = tv_get_string(&argvars[1]); + int id; + win_T *wp; + char_u *key; typval_T res; int c; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL)) + return; + + id = tv_get_number(&argvars[0]); + wp = win_id2wp(id); + key = tv_get_string(&argvars[1]); // If the popup has been closed don't consume the key. if (wp == NULL) return; @@ -2727,9 +2743,16 @@ close_all_popups(int force) f_popup_move(typval_T *argvars, typval_T *rettv UNUSED) { dict_T *dict; - int id = (int)tv_get_number(argvars); - win_T *wp = find_popup_win(id); - + int id; + win_T *wp; + + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_dict_arg(argvars, 1) == FAIL)) + return; + + id = (int)tv_get_number(argvars); + wp = find_popup_win(id); if (wp == NULL) return; // invalid {id} @@ -2754,10 +2777,17 @@ f_popup_move(typval_T *argvars, typval_T f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED) { dict_T *dict; - int id = (int)tv_get_number(argvars); - win_T *wp = find_popup_win(id); + int id; + win_T *wp; linenr_T old_firstline; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_dict_arg(argvars, 1) == FAIL)) + return; + + id = (int)tv_get_number(argvars); + wp = find_popup_win(id); if (wp == NULL) return; // invalid {id} diff --git a/src/proto/typval.pro b/src/proto/typval.pro --- a/src/proto/typval.pro +++ b/src/proto/typval.pro @@ -11,6 +11,7 @@ varnumber_T tv_get_bool_chk(typval_T *va float_T tv_get_float(typval_T *varp); int check_for_string_arg(typval_T *args, int idx); int check_for_nonempty_string_arg(typval_T *args, int idx); +int check_for_number_arg(typval_T *args, int idx); int check_for_dict_arg(typval_T *args, int idx); char_u *tv_get_string(typval_T *varp); char_u *tv_get_string_strict(typval_T *varp); diff --git a/src/sign.c b/src/sign.c --- a/src/sign.c +++ b/src/sign.c @@ -2274,7 +2274,11 @@ f_sign_getdefined(typval_T *argvars, typ return; if (argvars[0].v_type != VAR_UNKNOWN) + { + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; name = tv_get_string(&argvars[0]); + } sign_getlist(name, rettv->vval.v_list); } diff --git a/src/strings.c b/src/strings.c --- a/src/strings.c +++ b/src/strings.c @@ -795,9 +795,15 @@ byteidx(typval_T *argvars, typval_T *ret char_u *str; varnumber_T idx; + rettv->vval.v_number = -1; + + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_number_arg(argvars, 1) == FAIL)) + return; + str = tv_get_string_chk(&argvars[0]); idx = tv_get_number_chk(&argvars[1], NULL); - rettv->vval.v_number = -1; if (str == NULL || idx < 0) return; @@ -981,6 +987,12 @@ f_strgetchar(typval_T *argvars, typval_T int byteidx = 0; rettv->vval.v_number = -1; + + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_number_arg(argvars, 1) == FAIL)) + return; + str = tv_get_string_chk(&argvars[0]); if (str == NULL) return; @@ -1110,9 +1122,18 @@ f_strchars(typval_T *argvars, typval_T * void f_strdisplaywidth(typval_T *argvars, typval_T *rettv) { - char_u *s = tv_get_string(&argvars[0]); + char_u *s; int col = 0; + rettv->vval.v_number = -1; + + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 1) == FAIL))) + return; + + s = tv_get_string(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) col = (int)tv_get_number(&argvars[1]); diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -5689,6 +5689,11 @@ f_term_getattr(typval_T *argvars, typval {"reverse", HL_INVERSE}, }; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL)) + return; + attr = tv_get_number(&argvars[0]); name = tv_get_string_chk(&argvars[1]); if (name == NULL) diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -2614,7 +2614,7 @@ func Test_normal40_ctrl_bsl() set noim call assert_equal('are some words', getline(1)) call assert_false(&insertmode) - call assert_beeps("normal! \\", 'xt') + call assert_beeps("normal! \\") if has('cmdwin') " Using CTRL-\ CTRL-N in cmd window should close the window diff --git a/src/testdir/test_reltime.vim b/src/testdir/test_reltime.vim --- a/src/testdir/test_reltime.vim +++ b/src/testdir/test_reltime.vim @@ -24,8 +24,8 @@ func Test_reltime() call assert_true(reltimefloat(differs) < 0.1) call assert_true(reltimefloat(differs) > 0.0) - call assert_equal(0, reltime({})) - call assert_equal(0, reltime({}, {})) + call assert_equal([], reltime({})) + call assert_equal([], reltime({}, {})) endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -75,6 +75,41 @@ def Test_abs() endif enddef +def Test_add_blob() + var b1: blob = 0z12 + add(b1, 0x34) + assert_equal(0z1234, b1) + + var b2: blob # defaults to empty blob + add(b2, 0x67) + assert_equal(0z67, b2) + + var lines =<< trim END + var b: blob + add(b, "x") + END + CheckDefFailure(lines, 'E1012:', 2) + + lines =<< trim END + add(test_null_blob(), 123) + END + CheckDefExecAndScriptFailure(lines, 'E1131:', 1) + + lines =<< trim END + var b: blob = test_null_blob() + add(b, 123) + END + CheckDefExecFailure(lines, 'E1131:', 2) + + # Getting variable with NULL blob allocates a new blob at script level + lines =<< trim END + vim9script + var b: blob = test_null_blob() + add(b, 123) + END + CheckScriptSuccess(lines) +enddef + def Test_add_list() var l: list # defaults to empty list add(l, 9) @@ -120,41 +155,6 @@ def Test_add_list() CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3) enddef -def Test_add_blob() - var b1: blob = 0z12 - add(b1, 0x34) - assert_equal(0z1234, b1) - - var b2: blob # defaults to empty blob - add(b2, 0x67) - assert_equal(0z67, b2) - - var lines =<< trim END - var b: blob - add(b, "x") - END - CheckDefFailure(lines, 'E1012:', 2) - - lines =<< trim END - add(test_null_blob(), 123) - END - CheckDefExecAndScriptFailure(lines, 'E1131:', 1) - - lines =<< trim END - var b: blob = test_null_blob() - add(b, 123) - END - CheckDefExecFailure(lines, 'E1131:', 2) - - # Getting variable with NULL blob allocates a new blob at script level - lines =<< trim END - vim9script - var b: blob = test_null_blob() - add(b, 123) - END - CheckScriptSuccess(lines) -enddef - def Test_and() CheckDefAndScriptFailure2(['and("x", 0x2)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') CheckDefAndScriptFailure2(['and(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1030: Using a String as a Number') @@ -171,6 +171,30 @@ def Test_append() append(0, 'zero') assert_equal('zero', getline(1)) + append(0, {a: 10}) + assert_equal("{'a': 10}", getline(1)) + append(0, function('min')) + assert_equal("function('min')", getline(1)) + CheckDefAndScriptFailure2(['append([1], "x")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E745: Using a List as a Number') + bwipe! +enddef + +def Test_appendbufline() + new + var bnum: number = bufnr() + :wincmd w + appendbufline(bnum, 0, range(3)) + var res1: number = appendbufline(bnum, 1, 'one') + assert_equal(0, res1) + var res2: bool = appendbufline(bnum, 3, 'two') + assert_equal(false, res2) + assert_equal(['0', 'one', '1', 'two', '2', ''], getbufline(bnum, 1, '$')) + appendbufline(bnum, 0, 'zero') + assert_equal(['zero'], getbufline(bnum, 1)) + CheckDefFailure(['appendbufline([1], 1, "x")'], 'E1013: Argument 1: type mismatch, expected string but got list') + CheckDefFailure(['appendbufline(1, [1], "x")'], 'E1013: Argument 2: type mismatch, expected string but got list') + CheckDefFailure(['appendbufline(1, 1, {"a": 10})'], 'E1013: Argument 3: type mismatch, expected string but got dict') + bnum->bufwinid()->win_gotoid() bwipe! enddef @@ -190,6 +214,10 @@ def Test_argv() CheckDefFailure(['argv("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string') enddef +def Test_assert_beeps() + CheckDefAndScriptFailure2(['assert_beeps(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') +enddef + def Test_assert_equalfile() CheckDefFailure(['assert_equalfile(1, "f2")'], 'E1013: Argument 1: type mismatch, expected string but got number') CheckDefFailure(['assert_equalfile("f1", true)'], 'E1013: Argument 2: type mismatch, expected string but got bool') @@ -207,6 +235,10 @@ def Test_assert_match() CheckDefFailure(['assert_match("a", "b", null)'], 'E1013: Argument 3: type mismatch, expected string but got special') enddef +def Test_assert_nobeep() + CheckDefAndScriptFailure2(['assert_nobeep(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') +enddef + def Test_assert_notmatch() CheckDefFailure(['assert_notmatch({}, "b")'], 'E1013: Argument 1: type mismatch, expected string but got dict') CheckDefFailure(['assert_notmatch("a", 1)'], 'E1013: Argument 2: type mismatch, expected string but got number') @@ -328,6 +360,16 @@ def Test_byte2line() assert_equal(-1, byte2line(0)) enddef +def Test_byteidx() + CheckDefAndScriptFailure2(['byteidx(1, 2)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['byteidx("a", "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + +def Test_byteidxcomp() + CheckDefAndScriptFailure2(['byteidxcomp(1, 2)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['byteidxcomp("a", "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + def Test_call_call() var l = [3, 2, 1] call('reverse', [l]) @@ -355,6 +397,12 @@ def Test_ch_close_in() CheckDefFailure(['ch_close_in(true)'], 'E1013: Argument 1: type mismatch, expected channel but got bool') enddef +def Test_ch_getjob() + CheckDefAndScriptFailure2(['ch_getjob(1)'], 'E1013: Argument 1: type mismatch, expected channel but got number', 'E475: Invalid argument:') + CheckDefAndScriptFailure2(['ch_getjob({"a": 10})'], 'E1013: Argument 1: type mismatch, expected channel but got dict', 'E731: Using a Dictionary as a String') + assert_equal(0, ch_getjob(test_null_channel())) +enddef + def Test_ch_info() if !has('channel') CheckFeature channel @@ -381,6 +429,46 @@ def Test_ch_open() CheckDefAndScriptFailure2(['ch_open("a", [1])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 2') enddef +def Test_ch_read() + if !has('channel') + CheckFeature channel + endif + CheckDefAndScriptFailure2(['ch_read(1)'], 'E1013: Argument 1: type mismatch, expected channel but got number', 'E475: Invalid argument') + CheckDefAndScriptFailure2(['ch_read(test_null_channel(), [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') +enddef + +def Test_ch_readblob() + if !has('channel') + CheckFeature channel + endif + CheckDefAndScriptFailure2(['ch_readblob(1)'], 'E1013: Argument 1: type mismatch, expected channel but got number', 'E475: Invalid argument') + CheckDefAndScriptFailure2(['ch_readblob(test_null_channel(), [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') +enddef + +def Test_ch_readraw() + if !has('channel') + CheckFeature channel + endif + CheckDefAndScriptFailure2(['ch_readraw(1)'], 'E1013: Argument 1: type mismatch, expected channel but got number', 'E475: Invalid argument') + CheckDefAndScriptFailure2(['ch_readraw(test_null_channel(), [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') +enddef + +def Test_ch_setoptions() + if !has('channel') + CheckFeature channel + endif + CheckDefAndScriptFailure2(['ch_setoptions(1, {})'], 'E1013: Argument 1: type mismatch, expected channel but got number', 'E475: Invalid argument') + CheckDefFailure(['ch_setoptions(test_null_channel(), [])'], 'E1013: Argument 2: type mismatch, expected dict but got list') +enddef + +def Test_ch_status() + if !has('channel') + CheckFeature channel + endif + CheckDefAndScriptFailure2(['ch_status(1)'], 'E1013: Argument 1: type mismatch, expected channel but got number', 'E475: Invalid argument') + CheckDefAndScriptFailure2(['ch_status(test_null_channel(), [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') +enddef + def Test_char2nr() char2nr('あ', true)->assert_equal(12354) @@ -440,6 +528,13 @@ def Test_col() bw! enddef +def Test_complete_info() + CheckDefFailure(['complete_info("")'], 'E1013: Argument 1: type mismatch, expected list but got string') + CheckDefFailure(['complete_info({})'], 'E1013: Argument 1: type mismatch, expected list but got dict') + assert_equal({'pum_visible': 0, 'mode': '', 'selected': -1, 'items': []}, complete_info()) + assert_equal({'mode': '', 'items': []}, complete_info(['mode', 'items'])) +enddef + def Test_confirm() if !has('dialog_con') && !has('dialog_gui') CheckFeature dialog_con @@ -450,13 +545,6 @@ def Test_confirm() assert_fails('confirm("yes", "maybe", 2, true)', 'E1174:') enddef -def Test_complete_info() - CheckDefFailure(['complete_info("")'], 'E1013: Argument 1: type mismatch, expected list but got string') - CheckDefFailure(['complete_info({})'], 'E1013: Argument 1: type mismatch, expected list but got dict') - assert_equal({'pum_visible': 0, 'mode': '', 'selected': -1, 'items': []}, complete_info()) - assert_equal({'mode': '', 'items': []}, complete_info(['mode', 'items'])) -enddef - def Test_copy_return_type() var l = copy([1, 2, 3]) var res = 0 @@ -514,6 +602,11 @@ def Test_diff_filler() assert_equal(0, diff_filler('.')) enddef +def Test_echoraw() + CheckDefAndScriptFailure2(['echoraw(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['echoraw(["x"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') +enddef + def Test_escape() CheckDefFailure(['escape("a", 10)'], 'E1013: Argument 2: type mismatch, expected string but got number') CheckDefFailure(['escape(10, " ")'], 'E1013: Argument 1: type mismatch, expected string but got number') @@ -604,25 +697,6 @@ def Test_extend_arg_types() CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1013: Argument 2: type mismatch, expected list but got list') enddef -def Test_extendnew() - assert_equal([1, 2, 'a'], extendnew([1, 2], ['a'])) - assert_equal({one: 1, two: 'a'}, extendnew({one: 1}, {two: 'a'})) - - CheckDefFailure(['extendnew({a: 1}, 42)'], 'E1013: Argument 2: type mismatch, expected dict but got number') - CheckDefFailure(['extendnew({a: 1}, [42])'], 'E1013: Argument 2: type mismatch, expected dict but got list') - CheckDefFailure(['extendnew([1, 2], "x")'], 'E1013: Argument 2: type mismatch, expected list but got string') - CheckDefFailure(['extendnew([1, 2], {x: 1})'], 'E1013: Argument 2: type mismatch, expected list but got dict') -enddef - -def Test_extend_return_type() - var l = extend([1, 2], [3]) - var res = 0 - for n in l - res += n - endfor - res->assert_equal(6) -enddef - func g:ExtendDict(d) call extend(a:d, #{xx: 'x'}) endfunc @@ -673,6 +747,15 @@ def Test_extend_list_item_type() CheckScriptFailure(['vim9script'] + lines, 'E1012:', 1) enddef +def Test_extend_return_type() + var l = extend([1, 2], [3]) + var res = 0 + for n in l + res += n + endfor + res->assert_equal(6) +enddef + def Test_extend_with_error_function() var lines =<< trim END vim9script @@ -693,6 +776,16 @@ def Test_extend_with_error_function() CheckScriptFailure(lines, 'E1001: Variable not found: m') enddef +def Test_extendnew() + assert_equal([1, 2, 'a'], extendnew([1, 2], ['a'])) + assert_equal({one: 1, two: 'a'}, extendnew({one: 1}, {two: 'a'})) + + CheckDefFailure(['extendnew({a: 1}, 42)'], 'E1013: Argument 2: type mismatch, expected dict but got number') + CheckDefFailure(['extendnew({a: 1}, [42])'], 'E1013: Argument 2: type mismatch, expected dict but got list') + CheckDefFailure(['extendnew([1, 2], "x")'], 'E1013: Argument 2: type mismatch, expected list but got string') + CheckDefFailure(['extendnew([1, 2], {x: 1})'], 'E1013: Argument 2: type mismatch, expected list but got dict') +enddef + def Test_feedkeys() CheckDefFailure(['feedkeys(10)'], 'E1013: Argument 1: type mismatch, expected string but got number') CheckDefFailure(['feedkeys("x", 10)'], 'E1013: Argument 2: type mismatch, expected string but got number') @@ -703,36 +796,6 @@ def Test_feedkeys() unlet g:TestVar enddef -def Test_indent() - CheckDefAndScriptFailure2(['indent([1])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E745: Using a List as a Number') - CheckDefAndScriptFailure2(['indent(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1138: Using a Bool as a Number') - assert_equal(0, indent(1)) -enddef - -def Test_input() - CheckDefFailure(['input(5)'], 'E1013: Argument 1: type mismatch, expected string but got number') - CheckDefAndScriptFailure2(['input(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') - CheckDefFailure(['input("p", 10)'], 'E1013: Argument 2: type mismatch, expected string but got number') - CheckDefAndScriptFailure2(['input("p", "q", 20)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E180: Invalid complete value') -enddef - -def Test_inputdialog() - CheckDefFailure(['inputdialog(5)'], 'E1013: Argument 1: type mismatch, expected string but got number') - CheckDefAndScriptFailure2(['inputdialog(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') - CheckDefFailure(['inputdialog("p", 10)'], 'E1013: Argument 2: type mismatch, expected string but got number') - CheckDefFailure(['inputdialog("p", "q", 20)'], 'E1013: Argument 3: type mismatch, expected string but got number') -enddef - -def Test_job_info_return_type() - if has('job') - job_start(&shell) - var jobs = job_info() - assert_equal('list', typename(jobs)) - assert_equal('dict', typename(job_info(jobs[0]))) - job_stop(jobs[0]) - endif -enddef - def Test_filereadable() assert_false(filereadable("")) assert_false(filereadable(test_null_string())) @@ -928,6 +991,8 @@ enddef def Test_garbagecollect() garbagecollect(true) + CheckDefAndScriptFailure2(['garbagecollect("1")'], 'E1013: Argument 1: type mismatch, expected bool but got string', 'E1135: Using a String as a Bool') + CheckDefAndScriptFailure2(['garbagecollect(20)'], 'E1013: Argument 1: type mismatch, expected bool but got number', 'E1023: Using a Number as a Bool') enddef def Test_getbufinfo() @@ -967,6 +1032,19 @@ def Test_getchar() while getchar(0) endwhile getchar(true)->assert_equal(0) + getchar(1)->assert_equal(0) + CheckDefAndScriptFailure2(['getchar(2)'], 'E1013: Argument 1: type mismatch, expected bool but got number', 'E1023: Using a Number as a Bool') + CheckDefAndScriptFailure2(['getchar("1")'], 'E1013: Argument 1: type mismatch, expected bool but got string', 'E1135: Using a String as a Bool') +enddef + +def Test_getcharpos() + CheckDefAndScriptFailure2(['getcharpos(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['getcharpos(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') +enddef + +def Test_getcharstr() + CheckDefAndScriptFailure2(['getcharstr(2)'], 'E1013: Argument 1: type mismatch, expected bool but got number', 'E1023: Using a Number as a Bool') + CheckDefAndScriptFailure2(['getcharstr("1")'], 'E1013: Argument 1: type mismatch, expected bool but got string', 'E1135: Using a String as a Bool') enddef def Test_getenv() @@ -1003,14 +1081,6 @@ def Test_getcwd() CheckDefFailure(['getcwd(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string') enddef -def Test_getloclist_return_type() - var l = getloclist(1) - l->assert_equal([]) - - var d = getloclist(1, {items: 0}) - d->assert_equal({items: []}) -enddef - def Test_getfontname() CheckDefFailure(['getfontname(10)'], 'E1013: Argument 1: type mismatch, expected string but got number') enddef @@ -1072,6 +1142,19 @@ def Test_getline() CheckDefExecAndScriptFailure(lines, 'E1209:') enddef +def Test_getloclist() + CheckDefAndScriptFailure2(['getloclist("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') + CheckDefAndScriptFailure2(['getloclist(1, [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') +enddef + +def Test_getloclist_return_type() + var l = getloclist(1) + l->assert_equal([]) + + var d = getloclist(1, {items: 0}) + d->assert_equal({items: []}) +enddef + def Test_getmarklist() CheckDefFailure(['getmarklist([])'], 'E1013: Argument 1: type mismatch, expected string but got list') assert_equal([], getmarklist(10000)) @@ -1197,6 +1280,11 @@ def Test_histadd() assert_equal('skyblue', histget('/', -1)) enddef +def Test_histget() + CheckDefAndScriptFailure2(['histget(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['histget("a", "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + def Test_histnr() CheckDefFailure(['histnr(10)'], 'E1013: Argument 1: type mismatch, expected string but got number') assert_equal(-1, histnr('abc')) @@ -1219,10 +1307,30 @@ def Test_iconv() assert_equal('abc', iconv('abc', 'fromenc', 'toenc')) enddef +def Test_indent() + CheckDefAndScriptFailure2(['indent([1])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E745: Using a List as a Number') + CheckDefAndScriptFailure2(['indent(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1138: Using a Bool as a Number') + assert_equal(0, indent(1)) +enddef + def Test_index() index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3) enddef +def Test_input() + CheckDefFailure(['input(5)'], 'E1013: Argument 1: type mismatch, expected string but got number') + CheckDefAndScriptFailure2(['input(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') + CheckDefFailure(['input("p", 10)'], 'E1013: Argument 2: type mismatch, expected string but got number') + CheckDefAndScriptFailure2(['input("p", "q", 20)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E180: Invalid complete value') +enddef + +def Test_inputdialog() + CheckDefFailure(['inputdialog(5)'], 'E1013: Argument 1: type mismatch, expected string but got number') + CheckDefAndScriptFailure2(['inputdialog(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') + CheckDefFailure(['inputdialog("p", 10)'], 'E1013: Argument 2: type mismatch, expected string but got number') + CheckDefFailure(['inputdialog("p", "q", 20)'], 'E1013: Argument 3: type mismatch, expected string but got number') +enddef + def Test_inputlist() CheckDefFailure(['inputlist(10)'], 'E1013: Argument 1: type mismatch, expected list but got number') CheckDefFailure(['inputlist("abc")'], 'E1013: Argument 1: type mismatch, expected list but got string') @@ -1289,12 +1397,47 @@ def Test_isdirectory() assert_false(isdirectory('NonExistingDir')) enddef +def Test_islocked() + CheckDefAndScriptFailure2(['islocked(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['var n1: number = 10', 'islocked(n1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + g:v1 = 10 + assert_false(islocked('g:v1')) + lockvar g:v1 + assert_true(islocked('g:v1')) + unlet g:v1 +enddef + def Test_items() CheckDefFailure(['[]->items()'], 'E1013: Argument 1: type mismatch, expected dict but got list') assert_equal([['a', 10], ['b', 20]], {'a': 10, 'b': 20}->items()) assert_equal([], {}->items()) enddef +def Test_job_getchannel() + CheckDefAndScriptFailure2(['job_getchannel("a")'], 'E1013: Argument 1: type mismatch, expected job but got string', 'E475: Invalid argument') + assert_fails('job_getchannel(test_null_job())', 'E916: not a valid job') +enddef + +def Test_job_info() + CheckDefAndScriptFailure2(['job_info("a")'], 'E1013: Argument 1: type mismatch, expected job but got string', 'E475: Invalid argument') + assert_fails('job_info(test_null_job())', 'E916: not a valid job') +enddef + +def Test_job_info_return_type() + if has('job') + job_start(&shell) + var jobs = job_info() + assert_equal('list', typename(jobs)) + assert_equal('dict', typename(job_info(jobs[0]))) + job_stop(jobs[0]) + endif +enddef + +def Test_job_status() + CheckDefAndScriptFailure2(['job_status("a")'], 'E1013: Argument 1: type mismatch, expected job but got string', 'E475: Invalid argument') + assert_equal('fail', job_status(test_null_job())) +enddef + def Test_js_decode() CheckDefFailure(['js_decode(10)'], 'E1013: Argument 1: type mismatch, expected string but got number') assert_equal([1, 2], js_decode('[1,2]')) @@ -1318,6 +1461,8 @@ enddef def Test_line() assert_fails('line(true)', 'E1174:') + CheckDefAndScriptFailure2(['line(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['line(".", "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') enddef def Test_line2byte() @@ -1476,6 +1621,7 @@ def Test_max() ? [1, max([2, 3])] : [4, 5] assert_equal([4, 5], l2) + CheckDefAndScriptFailure2(['max(5)'], 'E1013: Argument 1: type mismatch, expected list but got number', 'E712: Argument of max() must be a List or Dictionary') enddef def Test_menu_info() @@ -1497,6 +1643,7 @@ def Test_min() ? [1, min([2, 3])] : [4, 5] assert_equal([4, 5], l2) + CheckDefAndScriptFailure2(['min(5)'], 'E1013: Argument 1: type mismatch, expected list but got number', 'E712: Argument of min() must be a List or Dictionary') enddef def Test_mkdir() @@ -1506,6 +1653,18 @@ def Test_mkdir() delete('a', 'rf') enddef +def Test_mode() + CheckDefFailure(['mode("1")'], 'E1013: Argument 1: type mismatch, expected bool but got string') + CheckDefFailure(['mode(2)'], 'E1013: Argument 1: type mismatch, expected bool but got number') +enddef + +def Test_mzeval() + if !has('mzscheme') + CheckFeature mzscheme + endif + CheckDefAndScriptFailure2(['mzscheme(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') +enddef + def Test_nextnonblank() CheckDefFailure(['nextnonblank(null)'], 'E1013: Argument 1: type mismatch, expected string but got special') assert_equal(0, nextnonblank(1)) @@ -1520,6 +1679,18 @@ def Test_or() CheckDefFailure(['or(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string') enddef +def Test_pathshorten() + CheckDefAndScriptFailure2(['pathshorten(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['pathshorten("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + +def Test_perleval() + if !has('perl') + CheckFeature perl + endif + CheckDefAndScriptFailure2(['perleval(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') +enddef + def Test_popup_atcursor() CheckDefAndScriptFailure2(['popup_atcursor({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') CheckDefAndScriptFailure2(['popup_atcursor("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') @@ -1536,6 +1707,11 @@ def Test_popup_beval() CheckDefAndScriptFailure2(['popup_beval("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef +def Test_popup_clear() + CheckDefAndScriptFailure2(['popup_clear(["a"])'], 'E1013: Argument 1: type mismatch, expected bool but got list', 'E745: Using a List as a Number') + CheckDefAndScriptFailure2(['popup_clear(2)'], 'E1013: Argument 1: type mismatch, expected bool but got number', 'E1023: Using a Number as a Bool') +enddef + def Test_popup_create() # Pass variable of type 'any' to popup_create() var what: any = 'Hello' @@ -1549,6 +1725,31 @@ def Test_popup_dialog() CheckDefAndScriptFailure2(['popup_dialog("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef +def Test_popup_filter_menu() + CheckDefAndScriptFailure2(['popup_filter_menu("x", "")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['popup_filter_menu(1, 1)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') +enddef + +def Test_popup_filter_yesno() + CheckDefAndScriptFailure2(['popup_filter_yesno("x", "")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['popup_filter_yesno(1, 1)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') +enddef + +def Test_popup_getoptions() + CheckDefAndScriptFailure2(['popup_getoptions("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') + CheckDefAndScriptFailure2(['popup_getoptions(true)'], 'E1013: Argument 1: type mismatch, expected number but got bool', 'E1138: Using a Bool as a Number') +enddef + +def Test_popup_getpos() + CheckDefAndScriptFailure2(['popup_getpos("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') + CheckDefAndScriptFailure2(['popup_getpos(true)'], 'E1013: Argument 1: type mismatch, expected number but got bool', 'E1138: Using a Bool as a Number') +enddef + +def Test_popup_hide() + CheckDefAndScriptFailure2(['popup_hide("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') + CheckDefAndScriptFailure2(['popup_hide(true)'], 'E1013: Argument 1: type mismatch, expected number but got bool', 'E1138: Using a Bool as a Number') +enddef + def Test_popup_locate() CheckDefAndScriptFailure2(['popup_locate("a", 20)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') CheckDefAndScriptFailure2(['popup_locate(10, "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1030: Using a String as a Number') @@ -1559,11 +1760,26 @@ def Test_popup_menu() CheckDefAndScriptFailure2(['popup_menu("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef +def Test_popup_move() + CheckDefAndScriptFailure2(['popup_move("x", {})'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['popup_move(1, [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 2') +enddef + def Test_popup_notification() CheckDefAndScriptFailure2(['popup_notification({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E450: buffer number, text or a list required') CheckDefAndScriptFailure2(['popup_notification("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef +def Test_popup_setoptions() + CheckDefAndScriptFailure2(['popup_setoptions("x", {})'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['popup_setoptions(1, [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 2') +enddef + +def Test_popup_show() + CheckDefAndScriptFailure2(['popup_show("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') + CheckDefAndScriptFailure2(['popup_show(true)'], 'E1013: Argument 1: type mismatch, expected number but got bool', 'E1138: Using a Bool as a Number') +enddef + def Test_prevnonblank() CheckDefFailure(['prevnonblank(null)'], 'E1013: Argument 1: type mismatch, expected string but got special') assert_equal(0, prevnonblank(1)) @@ -1582,6 +1798,11 @@ def Test_prop_find() CheckDefAndScriptFailure2(['prop_find({"a": 10}, ["a"])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E730: Using a List as a String') enddef +def Test_prop_list() + CheckDefAndScriptFailure2(['prop_list("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['prop_list(1, [])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 2') +enddef + def Test_prop_type_add() CheckDefAndScriptFailure2(['prop_type_add({"a": 10}, "b")'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E731: Using a Dictionary as a String') CheckDefAndScriptFailure2(['prop_type_add("a", "b")'], 'E1013: Argument 2: type mismatch, expected dict but got string', 'E715: Dictionary required') @@ -1604,6 +1825,32 @@ def Test_prop_type_get() CheckDefAndScriptFailure2(['prop_type_get("a", "b")'], 'E1013: Argument 2: type mismatch, expected dict but got string', 'E715: Dictionary required') enddef +def Test_prop_type_list() + CheckDefAndScriptFailure2(['prop_type_list(["a"])'], 'E1013: Argument 1: type mismatch, expected dict but got list', 'E715: Dictionary required') + CheckDefAndScriptFailure2(['prop_type_list(2)'], 'E1013: Argument 1: type mismatch, expected dict but got number', 'E715: Dictionary required') +enddef + +def Test_py3eval() + if !has('python3') + CheckFeature python3 + endif + CheckDefAndScriptFailure2(['py3eval([2])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') +enddef + +def Test_pyeval() + if !has('python') + CheckFeature python + endif + CheckDefAndScriptFailure2(['pyeval([2])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') +enddef + +def Test_pyxeval() + if !has('python') && !has('python3') + CheckFeature python + endif + CheckDefAndScriptFailure2(['pyxeval([2])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') +enddef + def Test_rand() CheckDefFailure(['rand(10)'], 'E1013: Argument 1: type mismatch, expected list but got number') CheckDefFailure(['rand(["a"])'], 'E1013: Argument 1: type mismatch, expected list but got list') @@ -1704,6 +1951,13 @@ def Test_remote_peek() CheckDefAndScriptFailure2(['remote_peek("a5b6c7", [1])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E573: Invalid server id used') enddef +def Test_remote_read() + CheckFeature clientserver + CheckEnv DISPLAY + CheckDefAndScriptFailure2(['remote_read(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['remote_read("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + def Test_remote_startserver() CheckFeature clientserver CheckEnv DISPLAY @@ -1743,6 +1997,13 @@ def Test_reverse_return_type() res->assert_equal(6) enddef +def Test_rubyeval() + if !has('ruby') + CheckFeature ruby + endif + CheckDefAndScriptFailure2(['rubyeval([2])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') +enddef + def Test_screenattr() CheckDefFailure(['screenattr("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string') CheckDefFailure(['screenattr(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string') @@ -1813,6 +2074,7 @@ def Test_searchcount() maxcount: 99, incomplete: 0}) bwipe! + CheckDefAndScriptFailure2(['searchcount([1])'], 'E1013: Argument 1: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef def Test_searchpair() @@ -1956,6 +2218,27 @@ def Test_setfperm() CheckDefFailure(['setfperm("a", 0z10)'], 'E1013: Argument 2: type mismatch, expected string but got blob') enddef +def Test_setbufline() + new + var bnum = bufnr('%') + :wincmd w + setbufline(bnum, 1, range(1, 3)) + setbufline(bnum, 4, 'one') + setbufline(bnum, 5, 10) + setbufline(bnum, 6, ['two', 11]) + assert_equal(['1', '2', '3', 'one', '10', 'two', '11'], getbufline(bnum, 1, '$')) + CheckDefFailure(['setbufline([1], 1, "x")'], 'E1013: Argument 1: type mismatch, expected string but got list') + CheckDefFailure(['setbufline(1, [1], "x")'], 'E1013: Argument 2: type mismatch, expected string but got list') + CheckDefFailure(['setbufline(1, 1, {"a": 10})'], 'E1013: Argument 3: type mismatch, expected string but got dict') + bnum->bufwinid()->win_gotoid() + bw! +enddef + +def Test_setcellwidths() + CheckDefAndScriptFailure2(['setcellwidths(1)'], 'E1013: Argument 1: type mismatch, expected list but got number', 'E714: List required') + CheckDefAndScriptFailure2(['setcellwidths({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list but got dict', 'E714: List required') +enddef + def Test_setline() new setline(1, range(1, 4)) @@ -1964,6 +2247,9 @@ def Test_setline() assert_equal(['a', 'b', 'c', 'd'], getline(1, '$')) setline(1, 'one') assert_equal(['one', 'b', 'c', 'd'], getline(1, '$')) + setline(1, 10) + assert_equal(['10', 'b', 'c', 'd'], getline(1, '$')) + CheckDefAndScriptFailure2(['setline([1], "x")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E745: Using a List as a Number') bw! enddef @@ -1998,6 +2284,16 @@ def Test_sign_define() CheckDefAndScriptFailure2(['sign_define("a", ["b"])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef +def Test_sign_getdefined() + CheckDefAndScriptFailure2(['sign_getdefined(["x"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['sign_getdefined(2)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') +enddef + +def Test_sign_placelist() + CheckDefAndScriptFailure2(['sign_placelist("x")'], 'E1013: Argument 1: type mismatch, expected list but got string', 'E714: List required') + CheckDefAndScriptFailure2(['sign_placelist({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list but got dict', 'E714: List required') +enddef + def Test_sign_undefine() CheckDefAndScriptFailure2(['sign_undefine({})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E731: Using a Dictionary as a String') CheckDefAndScriptFailure2(['sign_undefine([1])'], 'E1013: Argument 1: type mismatch, expected list but got list', 'E155: Unknown sign:') @@ -2009,6 +2305,11 @@ def Test_sign_unplace() CheckDefAndScriptFailure2(['sign_unplace("a", ["b"])'], 'E1013: Argument 2: type mismatch, expected dict but got list', 'E715: Dictionary required') enddef +def Test_sign_unplacelist() + CheckDefAndScriptFailure2(['sign_unplacelist("x")'], 'E1013: Argument 1: type mismatch, expected list but got string', 'E714: List required') + CheckDefAndScriptFailure2(['sign_unplacelist({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list but got dict', 'E714: List required') +enddef + def Test_simplify() CheckDefFailure(['simplify(100)'], 'E1013: Argument 1: type mismatch, expected string but got number') call assert_equal('NonExistingFile', simplify('NonExistingFile')) @@ -2117,10 +2418,31 @@ def Test_str2nr() CheckScriptFailure(['vim9script', 'echo str2nr("123", 10, "x")'], 'E1135:') enddef +def Test_strcharlen() + CheckDefAndScriptFailure2(['strcharlen([1])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') + "abc"->strcharlen()->assert_equal(3) + strcharlen(99)->assert_equal(2) +enddef + def Test_strchars() strchars("A\u20dd", true)->assert_equal(1) enddef +def Test_strdisplaywidth() + CheckDefAndScriptFailure2(['strdisplaywidth(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['strdisplaywidth("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + +def Test_strftime() + CheckDefAndScriptFailure2(['strftime(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['strftime("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + +def Test_strgetchar() + CheckDefAndScriptFailure2(['strgetchar(1, 1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['strgetchar("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + def Test_stridx() CheckDefAndScriptFailure2(['stridx([1], "b")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') CheckDefAndScriptFailure2(['stridx("a", {})'], 'E1013: Argument 2: type mismatch, expected string but got dict', 'E731: Using a Dictionary as a String') @@ -2211,6 +2533,11 @@ def Test_tabpagenr() assert_equal(1, tabpagenr()) enddef +def Test_tabpagewinnr() + CheckDefAndScriptFailure2(['tabpagewinnr("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['tabpagewinnr(1, 2)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') +enddef + def Test_taglist() CheckDefAndScriptFailure2(['taglist([1])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') CheckDefAndScriptFailure2(['taglist("a", [2])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E730: Using a List as a String') @@ -2234,6 +2561,12 @@ def Test_term_getansicolors() CheckDefAndScriptFailure2(['term_getansicolors(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E745: Using a List as a Number') enddef +def Test_term_getattr() + CheckRunVimInTerminal + CheckDefAndScriptFailure2(['term_getattr("x", "a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['term_getattr(1, 2)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') +enddef + def Test_term_getcursor() CheckRunVimInTerminal CheckDefAndScriptFailure2(['term_getcursor({"a": 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict', 'E728: Using a Dictionary as a Number') @@ -2310,6 +2643,11 @@ def Test_test_option_not_set() CheckDefAndScriptFailure2(['test_option_not_set([])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E474: Invalid argument') enddef +def Test_test_override() + CheckDefAndScriptFailure2(['test_override(1, 1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['test_override("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') +enddef + def Test_test_setmouse() CheckDefAndScriptFailure2(['test_setmouse("a", 10)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E474: Invalid argument') CheckDefAndScriptFailure2(['test_setmouse(10, "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E474: Invalid argument') @@ -2392,6 +2730,11 @@ def Test_virtcol() bw! enddef +def Test_visualmode() + CheckDefFailure(['visualmode("1")'], 'E1013: Argument 1: type mismatch, expected bool but got string') + CheckDefFailure(['visualmode(2)'], 'E1013: Argument 1: type mismatch, expected bool but got number') +enddef + def Test_win_execute() assert_equal("\n" .. winnr(), win_execute(win_getid(), 'echo winnr()')) assert_equal("\n" .. winnr(), 'echo winnr()'->win_execute(win_getid())) @@ -2411,12 +2754,44 @@ def Test_win_getid() assert_equal(win_getid(), win_getid(1, 1)) enddef +def Test_win_gettype() + CheckDefAndScriptFailure2(['win_gettype("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + +def Test_win_gotoid() + CheckDefAndScriptFailure2(['win_gotoid("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + +def Test_win_id2tabwin() + CheckDefAndScriptFailure2(['win_id2tabwin("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + +def Test_win_id2win() + CheckDefAndScriptFailure2(['win_id2win("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + +def Test_win_screenpos() + CheckDefAndScriptFailure2(['win_screenpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + def Test_win_splitmove() split win_splitmove(1, 2, {vertical: true, rightbelow: true}) close enddef +def Test_winbufnr() + CheckDefAndScriptFailure2(['winbufnr("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + +def Test_winheight() + CheckDefAndScriptFailure2(['winheight("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + +def Test_winlayout() + CheckDefAndScriptFailure2(['winlayout("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') +enddef + def Test_winnr() CheckDefFailure(['winnr([])'], 'E1013: Argument 1: type mismatch, expected string but got list') assert_equal(1, winnr()) @@ -2449,38 +2824,6 @@ def Test_winsaveview() CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list but got dict', 1) enddef -def Test_win_gettype() - CheckDefAndScriptFailure2(['win_gettype("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_win_gotoid() - CheckDefAndScriptFailure2(['win_gotoid("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_win_id2tabwin() - CheckDefAndScriptFailure2(['win_id2tabwin("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_win_id2win() - CheckDefAndScriptFailure2(['win_id2win("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_win_screenpos() - CheckDefAndScriptFailure2(['win_screenpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_winbufnr() - CheckDefAndScriptFailure2(['winbufnr("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_winheight() - CheckDefAndScriptFailure2(['winheight("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - -def Test_winlayout() - CheckDefAndScriptFailure2(['winlayout("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') -enddef - def Test_winwidth() CheckDefAndScriptFailure2(['winwidth("x")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number') enddef diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -2982,7 +2982,7 @@ def Test_expr7_method_call() enddef RetVoid()->byteidx(3) END - CheckDefExecAndScriptFailure(lines, 'E1031:') + CheckDefExecFailure(lines, 'E1013:') enddef diff --git a/src/testing.c b/src/testing.c --- a/src/testing.c +++ b/src/testing.c @@ -340,10 +340,14 @@ assert_append_cmd_or_arg(garray_T *gap, static int assert_beeps(typval_T *argvars, int no_beep) { - char_u *cmd = tv_get_string_chk(&argvars[0]); + char_u *cmd; garray_T ga; int ret = 0; + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return 0; + + cmd = tv_get_string_chk(&argvars[0]); called_vim_beep = FALSE; suppress_errthrow = TRUE; emsg_silent = FALSE; @@ -367,7 +371,7 @@ assert_beeps(typval_T *argvars, int no_b } /* - * "assert_beeps(cmd [, error])" function + * "assert_beeps(cmd)" function */ void f_assert_beeps(typval_T *argvars, typval_T *rettv) @@ -376,7 +380,7 @@ f_assert_beeps(typval_T *argvars, typval } /* - * "assert_nobeep(cmd [, error])" function + * "assert_nobeep(cmd)" function */ void f_assert_nobeep(typval_T *argvars, typval_T *rettv) @@ -947,6 +951,11 @@ f_test_override(typval_T *argvars, typva int val; static int save_starting = -1; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_number_arg(argvars, 1) == FAIL)) + return; + if (argvars[0].v_type != VAR_STRING || (argvars[1].v_type) != VAR_NUMBER) emsg(_(e_invarg)); diff --git a/src/textprop.c b/src/textprop.c --- a/src/textprop.c +++ b/src/textprop.c @@ -769,9 +769,16 @@ f_prop_find(typval_T *argvars, typval_T void f_prop_list(typval_T *argvars, typval_T *rettv) { - linenr_T lnum = tv_get_number(&argvars[0]); + linenr_T lnum; buf_T *buf = curbuf; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN && + check_for_dict_arg(argvars, 1) == FAIL))) + return; + + lnum = tv_get_number(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) { if (get_bufnr_from_arg(&argvars[1], &buf) == FAIL) diff --git a/src/time.c b/src/time.c --- a/src/time.c +++ b/src/time.c @@ -169,6 +169,10 @@ f_reltime(typval_T *argvars UNUSED, typv # ifdef FEAT_RELTIME proftime_T res; proftime_T start; + long n1, n2; + + if (rettv_list_alloc(rettv) != OK) + return; if (argvars[0].v_type == VAR_UNKNOWN) { @@ -198,20 +202,15 @@ f_reltime(typval_T *argvars UNUSED, typv profile_sub(&res, &start); } - if (rettv_list_alloc(rettv) == OK) - { - long n1, n2; - # ifdef MSWIN - n1 = res.HighPart; - n2 = res.LowPart; + n1 = res.HighPart; + n2 = res.LowPart; # else - n1 = res.tv_sec; - n2 = res.tv_usec; + n1 = res.tv_sec; + n2 = res.tv_usec; # endif - list_append_number(rettv->vval.v_list, (varnumber_T)n1); - list_append_number(rettv->vval.v_list, (varnumber_T)n2); - } + list_append_number(rettv->vval.v_list, (varnumber_T)n1); + list_append_number(rettv->vval.v_list, (varnumber_T)n2); # endif } @@ -269,6 +268,12 @@ f_strftime(typval_T *argvars, typval_T * time_t seconds; char_u *p; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 1) == FAIL))) + return; + rettv->v_type = VAR_STRING; p = tv_get_string(&argvars[0]); diff --git a/src/typval.c b/src/typval.c --- a/src/typval.c +++ b/src/typval.c @@ -385,6 +385,23 @@ check_for_nonempty_string_arg(typval_T * } /* + * Give an error and return FAIL unless "tv" is a number. + */ + int +check_for_number_arg(typval_T *args, int idx) +{ + if (args[idx].v_type != VAR_NUMBER) + { + if (idx >= 0) + semsg(_(e_number_required_for_argument_nr), idx + 1); + else + emsg(_(e_numberreq)); + return FAIL; + } + return OK; +} + +/* * Give an error and return FAIL unless "tv" is a dict. */ int diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3162, +/**/ 3161, /**/ 3160,