diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-07-26 17:56:25 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-07-26 17:56:25 +0200 |
commit | 4fc224ca1cf2a8991c5ea17682a742c6ad5ad0f3 (patch) | |
tree | 4c752cc9133d073c9f0a085f94bdd38948598d7a /src | |
parent | 2547aa930b59f5e2bcb70e81d5a57ed461e59b4f (diff) |
patch 8.2.1300: Vim9: optional argument type not parsed properlyv8.2.1300
Problem: Vim9: optional argument type not parsed properly.
Solution: Skip over the "?". (issue #6507)
Diffstat (limited to 'src')
-rw-r--r-- | src/evalvars.c | 2 | ||||
-rw-r--r-- | src/proto/vim9compile.pro | 2 | ||||
-rw-r--r-- | src/testdir/test_vim9_func.vim | 13 | ||||
-rw-r--r-- | src/userfunc.c | 4 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 25 |
6 files changed, 37 insertions, 11 deletions
diff --git a/src/evalvars.c b/src/evalvars.c index e11fdac41f..f409f8c006 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1013,7 +1013,7 @@ skip_var_one(char_u *arg, int include_type) if (end == arg + 2 && end[-1] == ':') --end; if (*end == ':') - end = skip_type(skipwhite(end + 1)); + end = skip_type(skipwhite(end + 1), FALSE); } return end; } diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 6bf3eb315d..4108c04af4 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -6,7 +6,7 @@ type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap); int check_typval_type(type_T *expected, typval_T *actual_tv); int check_type(type_T *expected, type_T *actual, int give_msg); int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2); -char_u *skip_type(char_u *start); +char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap); char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 49be8f97a2..ade1fd1459 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -350,6 +350,19 @@ def Test_call_funcref() let Funcref: func(string) = function('UseNumber') END CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)') + + lines =<< trim END + vim9script + def EchoNr(nr = 34) + g:echo = nr + enddef + let Funcref: func(?number) = function('EchoNr') + Funcref() + assert_equal(34, g:echo) + Funcref(123) + assert_equal(123, g:echo) + END + CheckScriptSuccess(lines) enddef let SomeFunc = function('len') diff --git a/src/userfunc.c b/src/userfunc.c index 3e566f334a..d17e807dc6 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -123,7 +123,7 @@ one_function_arg(char_u *arg, garray_T *newargs, garray_T *argtypes, int skip) return arg; } type = skipwhite(p); - p = skip_type(type); + p = skip_type(type, TRUE); type = vim_strnsave(type, p - type); } else if (*skipwhite(p) != '=') @@ -2778,7 +2778,7 @@ def_function(exarg_T *eap, char_u *name_arg) if (*p == ':') { ret_type = skipwhite(p + 1); - p = skip_type(ret_type); + p = skip_type(ret_type, FALSE); if (p > ret_type) { ret_type = vim_strnsave(ret_type, p - ret_type); diff --git a/src/version.c b/src/version.c index 93bcc43247..68c7cf5013 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1300, +/**/ 1299, /**/ 1298, diff --git a/src/vim9compile.c b/src/vim9compile.c index 746c9aa1a2..1354a38b2c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -534,8 +534,16 @@ typval2type(typval_T *tv, garray_T *type_gap) if (name != NULL) // TODO: how about a builtin function? ufunc = find_func(name, FALSE, NULL); - if (ufunc != NULL && ufunc->uf_func_type != NULL) - return ufunc->uf_func_type; + if (ufunc != NULL) + { + // May need to get the argument types from default values by + // compiling the function. + if (ufunc->uf_def_status == UF_TO_BE_COMPILED + && compile_def_function(ufunc, TRUE, NULL) == FAIL) + return NULL; + if (ufunc->uf_func_type != NULL) + return ufunc->uf_func_type; + } } actual = alloc_type(type_gap); @@ -1916,12 +1924,15 @@ free_locals(cctx_T *cctx) /* * Skip over a type definition and return a pointer to just after it. + * When "optional" is TRUE then a leading "?" is accepted. */ char_u * -skip_type(char_u *start) +skip_type(char_u *start, int optional) { char_u *p = start; + if (optional && *p == '?') + ++p; while (ASCII_ISALNUM(*p) || *p == '_') ++p; @@ -1929,7 +1940,7 @@ skip_type(char_u *start) if (*skipwhite(p) == '<') { p = skipwhite(p); - p = skip_type(skipwhite(p + 1)); + p = skip_type(skipwhite(p + 1), FALSE); p = skipwhite(p); if (*p == '>') ++p; @@ -1945,7 +1956,7 @@ skip_type(char_u *start) { char_u *sp = p; - p = skip_type(p); + p = skip_type(p, TRUE); if (p == sp) return p; // syntax error if (*p == ',') @@ -1954,7 +1965,7 @@ skip_type(char_u *start) if (*p == ')') { if (p[1] == ':') - p = skip_type(skipwhite(p + 2)); + p = skip_type(skipwhite(p + 2), FALSE); else ++p; } @@ -1962,7 +1973,7 @@ skip_type(char_u *start) else { // handle func: return_type - p = skip_type(skipwhite(p + 1)); + p = skip_type(skipwhite(p + 1), FALSE); } } |