summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2021-07-10 13:15:41 +0200
committerBram Moolenaar <Bram@vim.org>2021-07-10 13:15:41 +0200
commit5b73992d8f82be7ac4b6f46c17f53ffb9640e5fa (patch)
treeff59a04ff0b60de8b527e5fe9d5e7df9bf50f5ce
parent9da32e4d578f4e93ef5397f9dd13e2c28b2a2595 (diff)
patch 8.2.3135: Vim9: builtin function arguments not checked at compile timev8.2.3135
Problem: Vim9: builtin function arguments not checked at compile time. Solution: Add more type checks. (Yegappan Lakshmanan, closes #8539)
-rw-r--r--src/channel.c5
-rw-r--r--src/errors.h2
-rw-r--r--src/evalfunc.c164
-rw-r--r--src/proto/typval.pro1
-rw-r--r--src/terminal.c5
-rw-r--r--src/testdir/test_search.vim12
-rw-r--r--src/testdir/test_textprop.vim2
-rw-r--r--src/testdir/test_vim9_builtin.vim524
-rw-r--r--src/testing.c5
-rw-r--r--src/textprop.c2
-rw-r--r--src/typval.c25
-rw-r--r--src/version.c2
12 files changed, 563 insertions, 186 deletions
diff --git a/src/channel.c b/src/channel.c
index 65757f1d7e..c0572d3311 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1311,6 +1311,11 @@ channel_open_func(typval_T *argvars)
jobopt_T opt;
channel_T *channel = NULL;
+ if (in_vim9script()
+ && (check_for_string_arg(argvars, 0) == FAIL
+ || check_for_dict_arg(argvars, 1) == FAIL))
+ return NULL;
+
address = tv_get_string(&argvars[0]);
if (argvars[1].v_type != VAR_UNKNOWN
&& (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL))
diff --git a/src/errors.h b/src/errors.h
index 3a76d9e959..14c5b8def8 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -492,3 +492,5 @@ EXTERN char e_regexp_number_after_dot_pos_search[]
INIT(= N_("E1204: No Number allowed after .: '\\%%%c'"));
EXTERN char e_no_white_space_allowed_between_option_and[]
INIT(= N_("E1205: No white space allowed between option and"));
+EXTERN char e_dict_required_for_argument_nr[]
+ INIT(= N_("E1206: Dictionary required for argument %d"));
diff --git a/src/evalfunc.c b/src/evalfunc.c
index bdfb570882..10477d1ca3 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -375,6 +375,18 @@ arg_list_or_dict(type_T *type, argcontext_T *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)
+ return OK;
+ arg_type_mismatch(&t_channel, type, context->arg_idx + 1);
+ return FAIL;
+}
+
+/*
* Check "type" is the same type as the previous argument.
* Must not be used for the first argcheck_T entry.
*/
@@ -444,15 +456,19 @@ arg_extend3(type_T *type, argcontext_T *context)
argcheck_T arg1_string[] = {arg_string};
argcheck_T arg1_number[] = {arg_number};
argcheck_T arg1_dict[] = {arg_dict_any};
-argcheck_T arg1_list_number[] = {arg_list_number};
-argcheck_T arg1_string_list[] = {arg_list_string};
+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[] = {arg_string_or_list};
+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_number[] = {arg_list_number, arg_list_number};
+argcheck_T arg2_list_nr[] = {arg_list_number, arg_list_number};
+argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string};
+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_execute[] = {arg_string_or_list, arg_string};
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
@@ -460,6 +476,7 @@ argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_e
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 arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
/*
@@ -750,9 +767,9 @@ static funcentry_T global_functions[] =
ret_number_bool, f_assert_beeps},
{"assert_equal", 2, 3, FEARG_2, NULL,
ret_number_bool, f_assert_equal},
- {"assert_equalfile", 2, 3, FEARG_1, NULL,
+ {"assert_equalfile", 2, 3, FEARG_1, arg3_string,
ret_number_bool, f_assert_equalfile},
- {"assert_exception", 1, 2, 0, NULL,
+ {"assert_exception", 1, 2, 0, arg2_string,
ret_number_bool, f_assert_exception},
{"assert_fails", 1, 5, FEARG_1, NULL,
ret_number_bool, f_assert_fails},
@@ -760,13 +777,13 @@ static funcentry_T global_functions[] =
ret_number_bool, f_assert_false},
{"assert_inrange", 3, 4, FEARG_3, NULL,
ret_number_bool, f_assert_inrange},
- {"assert_match", 2, 3, FEARG_2, NULL,
+ {"assert_match", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_match},
{"assert_nobeep", 1, 2, FEARG_1, NULL,
ret_number_bool, f_assert_nobeep},
{"assert_notequal", 2, 3, FEARG_2, NULL,
ret_number_bool, f_assert_notequal},
- {"assert_notmatch", 2, 3, FEARG_2, NULL,
+ {"assert_notmatch", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_notmatch},
{"assert_report", 1, 1, FEARG_1, NULL,
ret_number_bool, f_assert_report},
@@ -802,7 +819,7 @@ static funcentry_T global_functions[] =
},
{"browse", 4, 4, 0, NULL,
ret_string, f_browse},
- {"browsedir", 2, 2, 0, NULL,
+ {"browsedir", 2, 2, 0, arg2_string,
ret_string, f_browsedir},
{"bufadd", 1, 1, FEARG_1, arg1_string,
ret_number, f_bufadd},
@@ -838,11 +855,11 @@ static funcentry_T global_functions[] =
ret_any, f_call},
{"ceil", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_ceil)},
- {"ch_canread", 1, 1, FEARG_1, NULL,
+ {"ch_canread", 1, 1, FEARG_1, arg1_chan_or_job,
ret_number_bool, JOB_FUNC(f_ch_canread)},
- {"ch_close", 1, 1, FEARG_1, NULL,
+ {"ch_close", 1, 1, FEARG_1, arg1_chan_or_job,
ret_void, JOB_FUNC(f_ch_close)},
- {"ch_close_in", 1, 1, FEARG_1, NULL,
+ {"ch_close_in", 1, 1, FEARG_1, arg1_chan_or_job,
ret_void, JOB_FUNC(f_ch_close_in)},
{"ch_evalexpr", 2, 3, FEARG_1, NULL,
ret_any, JOB_FUNC(f_ch_evalexpr)},
@@ -852,13 +869,13 @@ static funcentry_T global_functions[] =
ret_number, JOB_FUNC(f_ch_getbufnr)},
{"ch_getjob", 1, 1, FEARG_1, NULL,
ret_job, JOB_FUNC(f_ch_getjob)},
- {"ch_info", 1, 1, FEARG_1, NULL,
+ {"ch_info", 1, 1, FEARG_1, arg1_chan_or_job,
ret_dict_any, JOB_FUNC(f_ch_info)},
{"ch_log", 1, 2, FEARG_1, NULL,
ret_void, JOB_FUNC(f_ch_log)},
- {"ch_logfile", 1, 2, FEARG_1, NULL,
+ {"ch_logfile", 1, 2, FEARG_1, arg2_string,
ret_void, JOB_FUNC(f_ch_logfile)},
- {"ch_open", 1, 2, FEARG_1, NULL,
+ {"ch_open", 1, 2, FEARG_1, arg2_string_dict,
ret_channel, JOB_FUNC(f_ch_open)},
{"ch_read", 1, 2, FEARG_1, NULL,
ret_string, JOB_FUNC(f_ch_read)},
@@ -880,9 +897,9 @@ static funcentry_T global_functions[] =
ret_number, f_char2nr},
{"charclass", 1, 1, FEARG_1, arg1_string,
ret_number, f_charclass},
- {"charcol", 1, 1, FEARG_1, NULL,
+ {"charcol", 1, 1, FEARG_1, arg1_string_or_list,
ret_number, f_charcol},
- {"charidx", 2, 3, FEARG_1, NULL,
+ {"charidx", 2, 3, FEARG_1, arg3_string_nr_bool,
ret_number, f_charidx},
{"chdir", 1, 1, FEARG_1, arg1_string,
ret_string, f_chdir},
@@ -890,7 +907,7 @@ static funcentry_T global_functions[] =
ret_number, f_cindent},
{"clearmatches", 0, 1, FEARG_1, arg1_number,
ret_void, f_clearmatches},
- {"col", 1, 1, FEARG_1, NULL,
+ {"col", 1, 1, FEARG_1, arg1_string_or_list,
ret_number, f_col},
{"complete", 2, 2, FEARG_2, NULL,
ret_void, f_complete},
@@ -898,7 +915,7 @@ static funcentry_T global_functions[] =
ret_number, f_complete_add},
{"complete_check", 0, 0, 0, NULL,
ret_number_bool, f_complete_check},
- {"complete_info", 0, 1, FEARG_1, arg1_string_list,
+ {"complete_info", 0, 1, FEARG_1, arg1_list_string,
ret_dict_any, f_complete_info},
{"confirm", 1, 4, FEARG_1, NULL,
ret_number, f_confirm},
@@ -924,7 +941,7 @@ static funcentry_T global_functions[] =
},
{"deepcopy", 1, 2, FEARG_1, NULL,
ret_first_arg, f_deepcopy},
- {"delete", 1, 2, FEARG_1, NULL,
+ {"delete", 1, 2, FEARG_1, arg2_string,
ret_number_bool, f_delete},
{"deletebufline", 2, 3, FEARG_1, NULL,
ret_number_bool, f_deletebufline},
@@ -974,9 +991,9 @@ static funcentry_T global_functions[] =
ret_number, f_filewritable},
{"filter", 2, 2, FEARG_1, NULL,
ret_first_arg, f_filter},
- {"finddir", 1, 3, FEARG_1, NULL,
+ {"finddir", 1, 3, FEARG_1, arg3_string_string_nr,
ret_string, f_finddir},
- {"findfile", 1, 3, FEARG_1, NULL,
+ {"findfile", 1, 3, FEARG_1, arg3_string_string_nr,
ret_string, f_findfile},
{"flatten", 1, 2, FEARG_1, NULL,
ret_list_any, f_flatten},
@@ -1114,7 +1131,7 @@ static funcentry_T global_functions[] =
ret_any, f_globpath},
{"has", 1, 2, 0, NULL,
ret_number_bool, f_has},
- {"has_key", 2, 2, FEARG_1, NULL,
+ {"has_key", 2, 2, FEARG_1, arg2_dict_string,
ret_number_bool, f_has_key},
{"haslocaldir", 0, 2, FEARG_1, arg2_number,
ret_number, f_haslocaldir},
@@ -1140,15 +1157,15 @@ static funcentry_T global_functions[] =
ret_string, f_hostname},
{"iconv", 3, 3, FEARG_1, arg3_string,
ret_string, f_iconv},
- {"indent", 1, 1, FEARG_1, NULL,
+ {"indent", 1, 1, FEARG_1, arg1_string_or_nr,
ret_number, f_indent},
{"index", 2, 4, FEARG_1, NULL,
ret_number, f_index},
- {"input", 1, 3, FEARG_1, NULL,
+ {"input", 1, 3, FEARG_1, arg3_string,
ret_string, f_input},
- {"inputdialog", 1, 3, FEARG_1, NULL,
+ {"inputdialog", 1, 3, FEARG_1, arg3_string,
ret_string, f_inputdialog},
- {"inputlist", 1, 1, FEARG_1, arg1_string_list,
+ {"inputlist", 1, 1, FEARG_1, arg1_list_string,
ret_number, f_inputlist},
{"inputrestore", 0, 0, 0, NULL,
ret_number_bool, f_inputrestore},
@@ -1196,7 +1213,7 @@ static funcentry_T global_functions[] =
ret_string, f_json_encode},
{"keys", 1, 1, FEARG_1, arg1_dict,
ret_list_string, f_keys},
- {"last_buffer_nr", 0, 0, 0, NULL, // obsolete
+ {"last_buffer_nr", 0, 0, 0, arg1_string_or_nr, // obsolete
ret_number, f_last_buffer_nr},
{"len", 1, 1, FEARG_1, NULL,
ret_number, f_len},
@@ -1214,7 +1231,7 @@ static funcentry_T global_functions[] =
ret_string, f_list2str},
{"listener_add", 1, 2, FEARG_2, NULL,
ret_number, f_listener_add},
- {"listener_flush", 0, 1, FEARG_1, NULL,
+ {"listener_flush", 0, 1, FEARG_1, arg1_string_or_nr,
ret_void, f_listener_flush},
{"listener_remove", 1, 1, FEARG_1, arg1_number,
ret_number_bool, f_listener_remove},
@@ -1276,7 +1293,7 @@ static funcentry_T global_functions[] =
},
{"min", 1, 1, FEARG_1, NULL,
ret_number, f_min},
- {"mkdir", 1, 3, FEARG_1, NULL,
+ {"mkdir", 1, 3, FEARG_1, arg3_string_string_nr,
ret_number_bool, f_mkdir},
{"mode", 0, 1, FEARG_1, NULL,
ret_string, f_mode},
@@ -1332,7 +1349,7 @@ static funcentry_T global_functions[] =
ret_void, PROP_FUNC(f_popup_hide)},
{"popup_list", 0, 0, 0, NULL,
ret_list_number, PROP_FUNC(f_popup_list)},
- {"popup_locate", 2, 2, 0, NULL,
+ {"popup_locate", 2, 2, 0, arg2_number,
ret_number, PROP_FUNC(f_popup_locate)},
{"popup_menu", 2, 2, FEARG_1, NULL,
ret_number, PROP_FUNC(f_popup_menu)},
@@ -1364,19 +1381,19 @@ static funcentry_T global_functions[] =
ret_void, PROP_FUNC(f_prop_add)},
{"prop_clear", 1, 3, FEARG_1, NULL,
ret_void, PROP_FUNC(f_prop_clear)},
- {"prop_find", 1, 2, FEARG_1, NULL,
+ {"prop_find", 1, 2, FEARG_1, arg2_dict_string,
ret_dict_any, PROP_FUNC(f_prop_find)},
{"prop_list", 1, 2, FEARG_1, NULL,
ret_list_dict_any, PROP_FUNC(f_prop_list)},
{"prop_remove", 1, 3, FEARG_1, NULL,
ret_number, PROP_FUNC(f_prop_remove)},
- {"prop_type_add", 2, 2, FEARG_1, NULL,
+ {"prop_type_add", 2, 2, FEARG_1, arg2_string_dict,
ret_void, PROP_FUNC(f_prop_type_add)},
- {"prop_type_change", 2, 2, FEARG_1, NULL,
+ {"prop_type_change", 2, 2, FEARG_1, arg2_string_dict,
ret_void, PROP_FUNC(f_prop_type_change)},
- {"prop_type_delete", 1, 2, FEARG_1, NULL,
+ {"prop_type_delete", 1, 2, FEARG_1, arg2_string_dict,
ret_void, PROP_FUNC(f_prop_type_delete)},
- {"prop_type_get", 1, 2, FEARG_1, NULL,
+ {"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,
ret_list_string, PROP_FUNC(f_prop_type_list)},
@@ -1408,9 +1425,9 @@ static funcentry_T global_functions[] =
NULL
#endif
},
- {"rand", 0, 1, FEARG_1, arg1_list_number,
+ {"rand", 0, 1, FEARG_1, arg1_list_nr,
ret_number, f_rand},
- {"range", 1, 3, FEARG_1, NULL,
+ {"range", 1, 3, FEARG_1, arg3_number,
ret_list_number, f_range},
{"readblob", 1, 1, FEARG_1, arg1_string,
ret_blob, f_readblob},
@@ -1418,7 +1435,7 @@ static funcentry_T global_functions[] =
ret_list_string, f_readdir},
{"readdirex", 1, 3, FEARG_1, NULL,
ret_list_dict_any, f_readdirex},
- {"readfile", 1, 3, FEARG_1, NULL,
+ {"readfile", 1, 3, FEARG_1, arg3_string_string_nr,
ret_list_string, f_readfile},
{"reduce", 2, 3, FEARG_1, NULL,
ret_any, f_reduce},
@@ -1426,17 +1443,17 @@ static funcentry_T global_functions[] =
ret_string, f_reg_executing},
{"reg_recording", 0, 0, 0, NULL,
ret_string, f_reg_recording},
- {"reltime", 0, 2, FEARG_1, arg2_list_number,
+ {"reltime", 0, 2, FEARG_1, arg2_list_nr,
ret_list_any, f_reltime},
- {"reltimefloat", 1, 1, FEARG_1, arg1_list_number,
+ {"reltimefloat", 1, 1, FEARG_1, arg1_list_nr,
ret_float, FLOAT_FUNC(f_reltimefloat)},
- {"reltimestr", 1, 1, FEARG_1, arg1_list_number,
+ {"reltimestr", 1, 1, FEARG_1, arg1_list_nr,
ret_string, f_reltimestr},
{"remote_expr", 2, 4, FEARG_1, NULL,
ret_string, f_remote_expr},
{"remote_foreground", 1, 1, FEARG_1, arg1_string,
ret_string, f_remote_foreground},
- {"remote_peek", 1, 2, FEARG_1, NULL,
+ {"remote_peek", 1, 2, FEARG_1, arg2_string,
ret_number, f_remote_peek},
{"remote_read", 1, 2, FEARG_1, NULL,
ret_string, f_remote_read},
@@ -1452,7 +1469,7 @@ static funcentry_T global_functions[] =
ret_first_arg, f_repeat},
{"resolve", 1, 1, FEARG_1, arg1_string,
ret_string, f_resolve},
- {"reverse", 1, 1, FEARG_1, NULL,
+ {"reverse", 1, 1, FEARG_1, arg1_list_or_blob,
ret_first_arg, f_reverse},
{"round", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_round)},
@@ -1490,7 +1507,7 @@ static funcentry_T global_functions[] =
ret_list_number, f_searchpairpos},
{"searchpos", 1, 5, FEARG_1, NULL,
ret_list_number, f_searchpos},
- {"server2client", 2, 2, FEARG_1, NULL,
+ {"server2client", 2, 2, FEARG_1, arg2_string,
ret_number_bool, f_server2client},
{"serverlist", 0, 0, 0, NULL,
ret_string, f_serverlist},
@@ -1544,7 +1561,7 @@ static funcentry_T global_functions[] =
ret_string, f_shellescape},
{"shiftwidth", 0, 1, FEARG_1, arg1_number,
ret_number, f_shiftwidth},
- {"sign_define", 1, 2, FEARG_1, NULL,
+ {"sign_define", 1, 2, FEARG_1, arg2_string_dict,
ret_any, SIGN_FUNC(f_sign_define)},
{"sign_getdefined", 0, 1, FEARG_1, NULL,
ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)},
@@ -1556,9 +1573,9 @@ static funcentry_T global_functions[] =
ret_number, SIGN_FUNC(f_sign_place)},
{"sign_placelist", 1, 1, FEARG_1, NULL,
ret_list_number, SIGN_FUNC(f_sign_placelist)},
- {"sign_undefine", 0, 1, FEARG_1, NULL,
+ {"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list,
ret_number_bool, SIGN_FUNC(f_sign_undefine)},
- {"sign_unplace", 1, 2, FEARG_1, NULL,
+ {"sign_unplace", 1, 2, FEARG_1, arg2_string_dict,
ret_number_bool, SIGN_FUNC(f_sign_unplace)},
{"sign_unplacelist", 1, 2, FEARG_1, NULL,
ret_list_number, SIGN_FUNC(f_sign_unplacelist)},
@@ -1618,7 +1635,7 @@ static funcentry_T global_functions[] =
},
{"strgetchar", 2, 2, FEARG_1, NULL,
ret_number, f_strgetchar},
- {"stridx", 2, 3, FEARG_1, NULL,
+ {"stridx", 2, 3, FEARG_1, arg3_string_string_nr,
ret_number, f_stridx},
{"string", 1, 1, FEARG_1, NULL,
ret_string, f_string},
@@ -1634,7 +1651,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
- {"strridx", 2, 3, FEARG_1, NULL,
+ {"strridx", 2, 3, FEARG_1, arg3_string_string_nr,
ret_number, f_strridx},
{"strtrans", 1, 1, FEARG_1, arg1_string,
ret_string, f_strtrans},
@@ -1670,7 +1687,7 @@ static funcentry_T global_functions[] =
ret_number, f_tabpagewinnr},
{"tagfiles", 0, 0, 0, NULL,
ret_list_string, f_tagfiles},
- {"taglist", 1, 2, FEARG_1, NULL,
+ {"taglist", 1, 2, FEARG_1, arg2_string,
ret_list_dict_any, f_taglist},
{"tan", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_tan)},
@@ -1680,13 +1697,13 @@ static funcentry_T global_functions[] =
ret_string, f_tempname},
{"term_dumpdiff", 2, 3, FEARG_1, NULL,
ret_number, TERM_FUNC(f_term_dumpdiff)},
- {"term_dumpload", 1, 2, FEARG_1, NULL,
+ {"term_dumpload", 1, 2, FEARG_1, arg2_string_dict,
ret_number, TERM_FUNC(f_term_dumpload)},
{"term_dumpwrite", 2, 3, FEARG_2, NULL,
ret_void, TERM_FUNC(f_term_dumpwrite)},
- {"term_getaltscreen", 1, 1, FEARG_1, NULL,
+ {"term_getaltscreen", 1, 1, FEARG_1, arg1_string_or_nr,
ret_number, TERM_FUNC(f_term_getaltscreen)},
- {"term_getansicolors", 1, 1, FEARG_1, NULL,
+ {"term_getansicolors", 1, 1, FEARG_1, arg1_string_or_nr,
ret_list_string,
#if defined(FEAT_TERMINAL) && (defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS))
f_term_getansicolors
@@ -1696,19 +1713,19 @@ static funcentry_T global_functions[] =
},
{"term_getattr", 2, 2, FEARG_1, NULL,
ret_number, TERM_FUNC(f_term_getattr)},
- {"term_getcursor", 1, 1, FEARG_1, NULL,
+ {"term_getcursor", 1, 1, FEARG_1, arg1_string_or_nr,
ret_list_any, TERM_FUNC(f_term_getcursor)},
- {"term_getjob", 1, 1, FEARG_1, NULL,
+ {"term_getjob", 1, 1, FEARG_1, arg1_string_or_nr,
ret_job, TERM_FUNC(f_term_getjob)},
{"term_getline", 2, 2, FEARG_1, NULL,
ret_string, TERM_FUNC(f_term_getline)},
- {"term_getscrolled", 1, 1, FEARG_1, NULL,
+ {"term_getscrolled", 1, 1, FEARG_1, arg1_string_or_nr,
ret_number, TERM_FUNC(f_term_getscrolled)},
- {"term_getsize", 1, 1, FEARG_1, NULL,
+ {"term_getsize", 1, 1, FEARG_1, arg1_string_or_nr,
ret_list_number, TERM_FUNC(f_term_getsize)},
- {"term_getstatus", 1, 1, FEARG_1, NULL,
+ {"term_getstatus", 1, 1, FEARG_1, arg1_string_or_nr,
ret_string, TERM_FUNC(f_term_getstatus)},
- {"term_gettitle", 1, 1, FEARG_1, NULL,
+ {"term_gettitle", 1, 1, FEARG_1, arg1_string_or_nr,
ret_string, TERM_FUNC(f_term_gettitle)},
{"term_gettty", 1, 2, FEARG_1, NULL,
ret_string, TERM_FUNC(f_term_gettty)},
@@ -1740,23 +1757,23 @@ static funcentry_T global_functions[] =
ret_void, TERM_FUNC(f_term_wait)},
{"terminalprops", 0, 0, 0, NULL,
ret_dict_string, f_terminalprops},
- {"test_alloc_fail", 3, 3, FEARG_1, NULL,
+ {"test_alloc_fail", 3, 3, FEARG_1, arg3_number,
ret_void, f_test_alloc_fail},
{"test_autochdir", 0, 0, 0, NULL,
ret_void, f_test_autochdir},
- {"test_feedinput", 1, 1, FEARG_1, NULL,
+ {"test_feedinput", 1, 1, FEARG_1, arg1_string,
ret_void, f_test_feedinput},
{"test_garbagecollect_now", 0, 0, 0, NULL,
ret_void, f_test_garbagecollect_now},
{"test_garbagecollect_soon", 0, 0, 0, NULL,
ret_void, f_test_garbagecollect_soon},
- {"test_getvalue", 1, 1, FEARG_1, NULL,
+ {"test_getvalue", 1, 1, FEARG_1, arg1_string,
ret_number, f_test_getvalue},
{"test_gui_drop_files", 4, 4, 0, NULL,
ret_void, f_test_gui_drop_files},
{"test_gui_mouse_event", 5, 5, 0, NULL,
ret_void, f_test_gui_mouse_event},
- {"test_ignore_error", 1, 1, FEARG_1, NULL,
+ {"test_ignore_error", 1, 1, FEARG_1, arg1_string,
ret_void, f_test_ignore_error},
{"test_null_blob", 0, 0, 0, NULL,
ret_blob, f_test_null_blob},
@@ -1774,7 +1791,7 @@ static funcentry_T global_functions[] =
ret_func_any, f_test_null_partial},
{"test_null_string", 0, 0, 0, NULL,
ret_string, f_test_null_string},
- {"test_option_not_set", 1, 1, FEARG_1, NULL,
+ {"test_option_not_set", 1, 1, FEARG_1, arg1_string,
ret_void, f_test_option_not_set},
{"test_override", 2, 2, FEARG_2, NULL,
ret_void, f_test_override},
@@ -1788,11 +1805,11 @@ static funcentry_T global_functions[] =
NULL
#endif
},
- {"test_setmouse", 2, 2, 0, NULL,
+ {"test_setmouse", 2, 2, 0, arg2_number,
ret_void, f_test_setmouse},
- {"test_settime", 1, 1, FEARG_1, NULL,
+ {"test_settime", 1, 1, FEARG_1, arg1_number,
ret_void, f_test_settime},
- {"test_srand_seed", 0, 1, FEARG_1, NULL,
+ {"test_srand_seed", 0, 1, FEARG_1, arg1_number,
ret_void, f_test_srand_seed},
{"test_unknown", 0, 0, 0, NULL,
ret_any, f_test_unknown},
@@ -1814,7 +1831,7 @@ static funcentry_T global_functions[] =
ret_string, f_toupper},
{"tr", 3, 3, FEARG_1, arg3_string,
ret_string, f_tr},
- {"trim", 1, 3, FEARG_1, NULL,
+ {"trim", 1, 3, FEARG_1, arg3_string_string_nr,
ret_string, f_trim},
{"trunc", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_trunc)},
@@ -1830,7 +1847,7 @@ static funcentry_T global_functions[] =
ret_list_any, f_uniq},
{"values", 1, 1, FEARG_1, arg1_dict,
ret_list_any, f_values},
- {"virtcol", 1, 1, FEARG_1, NULL,
+ {"virtcol", 1, 1, FEARG_1, arg1_string_or_list,
ret_number, f_virtcol},
{"visualmode", 0, 1, 0, NULL,
ret_string, f_visualmode},
@@ -2552,7 +2569,8 @@ f_charidx(typval_T *argvars, typval_T *rettv)
if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER
|| (argvars[2].v_type != VAR_UNKNOWN
- && argvars[2].v_type != VAR_NUMBER))
+ && argvars[2].v_type != VAR_NUMBER
+ && argvars[2].v_type != VAR_BOOL))
{
emsg(_(e_invarg));
return;
@@ -9763,6 +9781,12 @@ f_trim(typval_T *argvars, typval_T *rettv)
if (head == NULL)
return;
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING)
+ {
+ semsg(_(e_invarg2), tv_get_string(&argvars[1]));
+ return;
+ }
+
if (argvars[1].v_type == VAR_STRING)
{
mask = tv_get_string_buf_chk(&argvars[1], buf2);
diff --git a/src/proto/typval.pro b/src/proto/typval.pro
index ad20f8c4da..f6dd01ebb3 100644
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -11,6 +11,7 @@ varnumber_T tv_get_bool_chk(typval_T *varp, int *denote);
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_dict_arg(typval_T *args, int idx);
char_u *tv_get_string(typval_T *varp);
char_u *tv_get_string_strict(typval_T *varp);
char_u *tv_get_string_buf(typval_T *varp, char_u *buf);
diff --git a/src/terminal.c b/src/terminal.c
index e3945d03ac..9de516cc8b 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -5276,6 +5276,11 @@ term_load_dump(typval_T *argvars, typval_T *rettv, int do_diff)
FILE *fd2 = NULL;
char_u *textline = NULL;
+ if (in_vim9script()
+ && (check_for_string_arg(argvars, 0) == FAIL
+ || check_for_dict_arg(argvars, 1) == FAIL))
+ return;
+
// First open the files. If this fails bail out.
fname1 = tv_get_string_buf_chk(&argvars[0], buf1);
if (do_diff)
diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim
index 49e86f872d..045fa2ee8d 100644
--- a/src/testdir/test_search.vim
+++ b/src/testdir/test_search.vim
@@ -373,9 +373,9 @@ func Test_searchpairpos()
endfunc
func Test_searchpair_errors()
- call assert_fails("call searchpair([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: using List as a String')
- call assert_fails("call searchpair('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: using Funcref as a String')
- call assert_fails("call searchpair('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: using Dictionary as a String')
+ call assert_fails("call searchpair([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: Using a List as a String')
+ call assert_fails("call searchpair('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: Using a Funcref as a String')
+ call assert_fails("call searchpair('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: Using a Dictionary as a String')
call assert_fails("call searchpair('start', 'middle', 'end', 'flags', 'skip', 99, 100)", 'E475: Invalid argument: flags')
call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 'func', -99, 100)", 'E475: Invalid argument: -99')
call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 'func', 99, -100)", 'E475: Invalid argument: -100')
@@ -384,9 +384,9 @@ func Test_searchpair_errors()
endfunc
func Test_searchpairpos_errors()
- call assert_fails("call searchpairpos([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: using List as a String')
- call assert_fails("call searchpairpos('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: using Funcref as a String')
- call assert_fails("call searchpairpos('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: using Dictionary as a String')
+ call assert_fails("call searchpairpos([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: Using a List as a String')
+ call assert_fails("call searchpairpos('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: Using a Funcref as a String')
+ call assert_fails("call searchpairpos('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: Using a Dictionary as a String')
call assert_fails("call searchpairpos('start', 'middle', 'end', 'flags', 'skip', 99, 100)", 'E475: Invalid argument: flags')
call assert_fails("call searchpairpos('start', 'middle', 'end', 'bW', 'func', -99, 100)", 'E475: Invalid argument: -99')
call assert_fails("call searchpairpos('start', 'middle', 'end', 'bW', 'func', 99, -100)", 'E475: Invalid argument: -100')
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index e2de3ba937..82834e4d52 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -1340,7 +1340,7 @@ endfunc
func Test_prop_func_invalid_args()
call assert_fails('call prop_clear(1, 2, [])', 'E715:')
call assert_fails('call prop_clear(-1, 2)', 'E16:')
- call assert_fails('call prop_find(test_null_dict())', 'E474:')
+ call assert_fails('call prop_find(test_null_dict())', 'E715:')
call assert_fails('call prop_find({"bufnr" : []})', 'E730:')
call assert_fails('call prop_find({})', 'E968:')
call assert_fails('call prop_find({}, "x")', 'E474:')
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 5964ded70c..6b6278b8d0 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -156,8 +156,8 @@ def Test_add_blob()
enddef
def Test_and()
- CheckDefFailure(['echo and("x", 0x2)'], 'E1013: Argument 1: type mismatch, expected number but got string')
- CheckDefFailure(['echo and(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
+ 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')
enddef
def Test_append()
@@ -175,19 +175,42 @@ def Test_append()
enddef
def Test_argc()
- CheckDefFailure(['echo argc("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['argc("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
enddef
def Test_arglistid()
- CheckDefFailure(['echo arglistid("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
- CheckDefFailure(['echo arglistid(1, "y")'], 'E1013: Argument 2: type mismatch, expected number but got string')
- CheckDefFailure(['echo arglistid("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['arglistid("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['arglistid(1, "y")'], 'E1013: Argument 2: type mismatch, expected number but got string')
+ CheckDefFailure(['arglistid("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string')
enddef
def Test_argv()
- CheckDefFailure(['echo argv("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
- CheckDefFailure(['echo argv(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
- CheckDefFailure(['echo argv("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['argv("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['argv(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
+ CheckDefFailure(['argv("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+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')
+ CheckDefFailure(['assert_equalfile("f1", "f2", ["a"])'], 'E1013: Argument 3: type mismatch, expected string but got list<string>')
+enddef
+
+def Test_assert_exception()
+ CheckDefFailure(['assert_exception({})'], 'E1013: Argument 1: type mismatch, expected string but got dict<unknown>')
+ CheckDefFailure(['assert_exception("E1:", v:null)'], 'E1013: Argument 2: type mismatch, expected string but got special')
+enddef
+
+def Test_assert_match()
+ CheckDefFailure(['assert_match({}, "b")'], 'E1013: Argument 1: type mismatch, expected string but got dict<unknown>')
+ CheckDefFailure(['assert_match("a", 1)'], 'E1013: Argument 2: type mismatch, expected string but got number')
+ CheckDefFailure(['assert_match("a", "b", null)'], 'E1013: Argument 3: type mismatch, expected string but got special')
+enddef
+
+def Test_assert_notmatch()
+ CheckDefFailure(['assert_notmatch({}, "b")'], 'E1013: Argument 1: type mismatch, expected string but got dict<unknown>')
+ CheckDefFailure(['assert_notmatch("a", 1)'], 'E1013: Argument 2: type mismatch, expected string but got number')
+ CheckDefFailure(['assert_notmatch("a", "b", null)'], 'E1013: Argument 3: type mismatch, expected string but got special')
enddef
def Test_balloon_show()
@@ -222,6 +245,11 @@ def Test_browse()
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 4')
enddef
+def Test_browsedir()
+ CheckDefFailure(['browsedir({}, "b")'], 'E1013: Argument 1: type mismatch, expected string but got dict<unknown>')
+ CheckDefFailure(['browsedir("a", [])'], 'E1013: Argument 2: type mismatch, expected string but got list<unknown>')
+enddef
+
def Test_bufadd()
assert_fails('bufadd([])', 'E730:')
enddef
@@ -299,12 +327,51 @@ def Test_call_call()
l->assert_equal([1, 2, 3])
enddef
+def Test_ch_canread()
+ if !has('channel')
+ CheckFeature channel
+ endif
+ CheckDefFailure(['ch_canread(10)'], 'E1013: Argument 1: type mismatch, expected channel but got number')
+enddef
+
+def Test_ch_close()
+ if !has('channel')
+ CheckFeature channel
+ endif
+ CheckDefFailure(['ch_close("c")'], 'E1013: Argument 1: type mismatch, expected channel but got string')
+enddef
+
+def Test_ch_close_in()
+ if !has('channel')
+ CheckFeature channel
+ endif
+ CheckDefFailure(['ch_close_in(true)'], 'E1013: Argument 1: type mismatch, expected channel but got bool')
+enddef
+
+def Test_ch_info()
+ if !has('channel')
+ CheckFeature channel
+ endif
+ CheckDefFailure(['ch_info([1])'], 'E1013: Argument 1: type mismatch, expected channel but got list<number>')
+enddef
+
def Test_ch_logfile()
if !has('channel')
CheckFeature channel
endif
assert_fails('ch_logfile(true)', 'E1174:')
assert_fails('ch_logfile("foo", true)', 'E1174:')
+
+ CheckDefAndScriptFailure2(['ch_logfile(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1')
+ CheckDefAndScriptFailure2(['ch_logfile("a", true)'], 'E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2')
+enddef
+
+def Test_ch_open()
+ if !has('channel')
+ CheckFeature channel
+ endif
+ CheckDefAndScriptFailure2(['ch_open({"a": 10}, "a")'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1')
+ CheckDefAndScriptFailure2(['ch_open("a", [1])'], 'E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2')
enddef
def Test_char2nr()
@@ -317,6 +384,17 @@ def Test_charclass()
assert_fails('charclass(true)', 'E1174:')
enddef
+def Test_charcol()
+ CheckDefFailure(['charcol(10)'], 'E1013: Argument 1: type mismatch, expected string but got number')
+ CheckDefFailure(['charcol({a: 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>')
+enddef
+
+def Test_charidx()
+ CheckDefFailure(['charidx("a", "b")'], 'E1013: Argument 2: type mismatch, expected number but got string')
+ CheckDefFailure(['charidx(0z10, 1)'], 'E1013: Argument 1: type mismatch, expected string but got blob')
+ CheckDefFailure(['charidx("a", 1, "")'], 'E1013: Argument 3: type mismatch, expected bool but got string')
+enddef
+
def Test_chdir()
assert_fails('chdir(true)', 'E1174:')
enddef
@@ -329,7 +407,7 @@ def Test_cindent()
enddef
def Test_clearmatches()
- CheckDefFailure(['echo clearmatches("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['clearmatches("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
enddef
def Test_col()
@@ -338,6 +416,11 @@ def Test_col()
col([1, '$'])->assert_equal(5)
assert_fails('col(true)', 'E1174:')
+
+ CheckDefFailure(['col(10)'], 'E1013: Argument 1: type mismatch, expected string but got number')
+ CheckDefFailure(['col({a: 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>')
+ CheckDefFailure(['col(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool')
+ bw!
enddef
def Test_confirm()
@@ -396,12 +479,15 @@ enddef
def Test_debugbreak()
CheckMSWindows
- CheckDefFailure(['echo debugbreak("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
+ CheckDefFailure(['debugbreak("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
enddef
<