0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.2.1300: Vim9: optional argument type not parsed properly

Problem:    Vim9: optional argument type not parsed properly.
Solution:   Skip over the "?". (issue #6507)
This commit is contained in:
Bram Moolenaar 2020-07-26 17:56:25 +02:00
parent 2547aa930b
commit 4fc224ca1c
6 changed files with 37 additions and 11 deletions

View File

@ -1013,7 +1013,7 @@ skip_var_one(char_u *arg, int include_type)
if (end == arg + 2 && end[-1] == ':') if (end == arg + 2 && end[-1] == ':')
--end; --end;
if (*end == ':') if (*end == ':')
end = skip_type(skipwhite(end + 1)); end = skip_type(skipwhite(end + 1), FALSE);
} }
return end; return end;
} }

View File

@ -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_typval_type(type_T *expected, typval_T *actual_tv);
int check_type(type_T *expected, type_T *actual, int give_msg); 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); 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); type_T *parse_type(char_u **arg, garray_T *type_gap);
char *vartype_name(vartype_T type); char *vartype_name(vartype_T type);
char *type_name(type_T *type, char **tofree); char *type_name(type_T *type, char **tofree);

View File

@ -350,6 +350,19 @@ def Test_call_funcref()
let Funcref: func(string) = function('UseNumber') let Funcref: func(string) = function('UseNumber')
END END
CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)') 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 enddef
let SomeFunc = function('len') let SomeFunc = function('len')

View File

@ -123,7 +123,7 @@ one_function_arg(char_u *arg, garray_T *newargs, garray_T *argtypes, int skip)
return arg; return arg;
} }
type = skipwhite(p); type = skipwhite(p);
p = skip_type(type); p = skip_type(type, TRUE);
type = vim_strnsave(type, p - type); type = vim_strnsave(type, p - type);
} }
else if (*skipwhite(p) != '=') else if (*skipwhite(p) != '=')
@ -2778,7 +2778,7 @@ def_function(exarg_T *eap, char_u *name_arg)
if (*p == ':') if (*p == ':')
{ {
ret_type = skipwhite(p + 1); ret_type = skipwhite(p + 1);
p = skip_type(ret_type); p = skip_type(ret_type, FALSE);
if (p > ret_type) if (p > ret_type)
{ {
ret_type = vim_strnsave(ret_type, p - ret_type); ret_type = vim_strnsave(ret_type, p - ret_type);

View File

@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1300,
/**/ /**/
1299, 1299,
/**/ /**/

View File

@ -534,8 +534,16 @@ typval2type(typval_T *tv, garray_T *type_gap)
if (name != NULL) if (name != NULL)
// TODO: how about a builtin function? // TODO: how about a builtin function?
ufunc = find_func(name, FALSE, NULL); ufunc = find_func(name, FALSE, NULL);
if (ufunc != NULL && ufunc->uf_func_type != NULL) if (ufunc != NULL)
return ufunc->uf_func_type; {
// 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); 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. * Skip over a type definition and return a pointer to just after it.
* When "optional" is TRUE then a leading "?" is accepted.
*/ */
char_u * char_u *
skip_type(char_u *start) skip_type(char_u *start, int optional)
{ {
char_u *p = start; char_u *p = start;
if (optional && *p == '?')
++p;
while (ASCII_ISALNUM(*p) || *p == '_') while (ASCII_ISALNUM(*p) || *p == '_')
++p; ++p;
@ -1929,7 +1940,7 @@ skip_type(char_u *start)
if (*skipwhite(p) == '<') if (*skipwhite(p) == '<')
{ {
p = skipwhite(p); p = skipwhite(p);
p = skip_type(skipwhite(p + 1)); p = skip_type(skipwhite(p + 1), FALSE);
p = skipwhite(p); p = skipwhite(p);
if (*p == '>') if (*p == '>')
++p; ++p;
@ -1945,7 +1956,7 @@ skip_type(char_u *start)
{ {
char_u *sp = p; char_u *sp = p;
p = skip_type(p); p = skip_type(p, TRUE);
if (p == sp) if (p == sp)
return p; // syntax error return p; // syntax error
if (*p == ',') if (*p == ',')
@ -1954,7 +1965,7 @@ skip_type(char_u *start)
if (*p == ')') if (*p == ')')
{ {
if (p[1] == ':') if (p[1] == ':')
p = skip_type(skipwhite(p + 2)); p = skip_type(skipwhite(p + 2), FALSE);
else else
++p; ++p;
} }
@ -1962,7 +1973,7 @@ skip_type(char_u *start)
else else
{ {
// handle func: return_type // handle func: return_type
p = skip_type(skipwhite(p + 1)); p = skip_type(skipwhite(p + 1), FALSE);
} }
} }