Mercurial > vim
changeset 19944:3055cd26e139 v8.2.0528
patch 8.2.0528: Vim9: function arguments insufficiently tested
Commit: https://github.com/vim/vim/commit/0b76b42d0a09fb6f1ed79cfc153da4edd6154c89
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Apr 7 22:05:08 2020 +0200
patch 8.2.0528: Vim9: function arguments insufficiently tested
Problem: Vim9: function arguments insufficiently tested.
Solution: Check types. Add more tests. Fix function with varargs only.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 07 Apr 2020 22:15:05 +0200 |
parents | a456f90669a4 |
children | 734ada3fa6de |
files | src/testdir/test_vim9_func.vim src/userfunc.c src/version.c src/vim9compile.c |
diffstat | 4 files changed, 58 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -130,6 +130,19 @@ def Test_call_def_varargs() assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) enddef +" Only varargs +def MyVarargsOnly(...args: list<string>): string + return join(args, ',') +enddef + +def Test_call_varargs_only() + assert_equal('', MyVarargsOnly()) + assert_equal('one', MyVarargsOnly('one')) + assert_equal('one,two', MyVarargsOnly('one', 'two')) + call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number') + call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number') +enddef + def Test_using_var_as_arg() call writefile(['def Func(x: number)', 'let x = 234', 'enddef'], 'Xdef') call assert_fails('so Xdef', 'E1006:')
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -3020,7 +3020,7 @@ ex_function(exarg_T *eap) if (eap->cmdidx == CMD_def) { - int lnum_save = SOURCING_LNUM; + int lnum_save = SOURCING_LNUM; // error messages are for the first function line SOURCING_LNUM = sourcing_lnum_top; @@ -3034,7 +3034,8 @@ ex_function(exarg_T *eap) // and uf_va_type. int len = argtypes.ga_len - (varargs ? 1 : 0); - fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len); + if (len > 0) + fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len); if (fp->uf_arg_types != NULL) { int i;
--- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 528, +/**/ 527, /**/ 526,
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -130,6 +130,8 @@ static int compile_expr1(char_u **arg, static int compile_expr2(char_u **arg, cctx_T *cctx); static int compile_expr3(char_u **arg, cctx_T *cctx); static void delete_def_function_contents(dfunc_T *dfunc); +static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); +static int check_type(type_T *expected, type_T *actual, int give_msg); /* * Lookup variable "name" in the local scope and return the index. @@ -1240,6 +1242,32 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu return FAIL; } + if (ufunc->uf_dfunc_idx >= 0) + { + int i; + + for (i = 0; i < argcount; ++i) + { + type_T *expected; + type_T *actual; + + if (i < regular_args) + { + if (ufunc->uf_arg_types == NULL) + continue; + expected = ufunc->uf_arg_types[i]; + } + else + expected = ufunc->uf_va_type->tt_member; + actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; + if (check_type(expected, actual, FALSE) == FAIL) + { + arg_type_mismatch(expected, actual, i + 1); + return FAIL; + } + } + } + // Turn varargs into a list. if (ufunc->uf_va_name != NULL) { @@ -2403,6 +2431,18 @@ type_mismatch(type_T *expected, type_T * vim_free(tofree2); } + static void +arg_type_mismatch(type_T *expected, type_T *actual, int argidx) +{ + char *tofree1, *tofree2; + + semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"), + argidx, + type_name(expected, &tofree1), type_name(actual, &tofree2)); + vim_free(tofree1); + vim_free(tofree2); +} + /* * Check if the expected and actual types match. */