summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-05-26 22:24:43 +0100
committerBram Moolenaar <Bram@vim.org>2022-05-26 22:24:43 +0100
commit31d9948e3a2529c2f619d56bdb48291dc261233d (patch)
tree9d190d121b8851b0d861455ba61b09fd03da8776
parent5cb53b7afe6bde8f2bf6fc6b65b86071b67a8554 (diff)
downloadvim-git-31d9948e3a2529c2f619d56bdb48291dc261233d.tar.gz
patch 8.2.5026: Vim9: a few lines not covered by testsv8.2.5026
Problem: Vim9: a few lines not covered by tests. Solution: Delete dead code. Add a few test cases. make "12->func()" work.
-rw-r--r--src/ex_docmd.c19
-rw-r--r--src/proto/ex_docmd.pro1
-rw-r--r--src/testdir/test_vim9_assign.vim57
-rw-r--r--src/testdir/test_vim9_func.vim57
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c4
-rw-r--r--src/vim9type.c93
7 files changed, 182 insertions, 51 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 6cf77155c..048c22436 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3507,6 +3507,18 @@ one_letter_cmd(char_u *p, cmdidx_T *idx)
}
/*
+ * Return TRUE if "cmd" starts with "123->", a number followed by a method
+ * call.
+ */
+ int
+number_method(char_u *cmd)
+{
+ char_u *p = skipdigits(cmd);
+
+ return p > cmd && (p = skipwhite(p))[0] == '-' && p[1] == '>';
+}
+
+/*
* Find an Ex command by its name, either built-in or user.
* Start of the name can be found at eap->cmd.
* Sets eap->cmdidx and returns a pointer to char after the command name.
@@ -3716,6 +3728,13 @@ find_ex_command(
}
}
+ // 1234->func() is a method call
+ if (number_method(eap->cmd))
+ {
+ eap->cmdidx = CMD_eval;
+ return eap->cmd;
+ }
+
// "g:", "s:" and "l:" are always assumed to be a variable, thus start
// an expression. A global/substitute/list command needs to use a
// longer name.
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index d67cb9a91..28f4c43dc 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -17,6 +17,7 @@ void apply_cmdmod(cmdmod_T *cmod);
void undo_cmdmod(cmdmod_T *cmod);
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
char_u *skip_option_env_lead(char_u *start);
+int number_method(char_u *cmd);
char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, int cmd, cctx_T *), cctx_T *cctx);
int modifier_len(char_u *cmd);
int cmd_exists(char_u *name);
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index b0ce39856..faa4928ea 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1121,6 +1121,9 @@ def Test_assignment_dict()
var dict4: dict<any> = {one: 1, two: '2'}
var dict5: dict<blob> = {one: 0z01, two: 0z02}
+ # check the type is OK
+ var events: dict<string> = v:event
+
# overwrite
dict3['key'] = 'another'
assert_equal(dict3, {key: 'another'})
@@ -2105,6 +2108,32 @@ def Test_var_declaration_fails()
va foo = 123
END
v9.CheckDefAndScriptFailure(lines, 'E1065:', 1)
+
+ lines =<< trim END
+ var foo: func(number
+ END
+ v9.CheckDefAndScriptFailure(lines, 'E110:', 1)
+
+ lines =<< trim END
+ var foo: func(number): func(
+ END
+ v9.CheckDefAndScriptFailure(lines, 'E110:', 1)
+
+ for type in ['num_ber',
+ 'anys', 'ani',
+ 'bools', 'boel',
+ 'blobs', 'blub',
+ 'channels', 'channol',
+ 'dicts', 'duct',
+ 'floats', 'floot',
+ 'funcs', 'funk',
+ 'jobs', 'jop',
+ 'lists', 'last'
+ 'numbers', 'numbar',
+ 'strings', 'strung',
+ 'voids', 'viod']
+ v9.CheckDefAndScriptFailure([$'var foo: {type}'], 'E1010:', 1)
+ endfor
enddef
def Test_var_declaration_inferred()
@@ -2118,6 +2147,34 @@ def Test_var_declaration_inferred()
echo GetList()->extend(['x'])
END
v9.CheckScriptFailure(lines, 'E1013:', 6)
+
+ lines =<< trim END
+ vim9script
+ def GetNr(): number
+ return 5
+ enddef
+ def TestOne()
+ var some = [function('len'), GetNr]
+ g:res = typename(some)
+ enddef
+ TestOne()
+ assert_equal('list<func(): number>', g:res)
+
+ def TestTwo()
+ var some = [function('len'), GetNr]
+ g:res = typename(some)
+ enddef
+ TestTwo()
+ assert_equal('list<func(): number>', g:res)
+ unlet g:res
+
+ # FIXME: why is the type different?
+ var first = [function('len'), GetNr]
+ assert_equal('list<func(...): number>', typename(first))
+ var second = [GetNr, function('len')]
+ assert_equal('list<func(...): number>', typename(second))
+ END
+ v9.CheckScriptSuccess(lines)
enddef
def Test_script_local_in_legacy()
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index fcf37d5f5..33a66151e 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -4051,6 +4051,63 @@ def Test_too_many_arguments()
echo [0, 1, 2]->map((_) => 123)
END
v9.CheckDefAndScriptFailure(lines, ['E176', 'E1106: One argument too many'], 1)
+
+ lines =<< trim END
+ vim9script
+ def OneArgument(arg: string)
+ echo arg
+ enddef
+ var Ref = OneArgument
+ Ref('a', 'b')
+ END
+ v9.CheckScriptFailure(lines, 'E118:')
+enddef
+
+def Test_funcref_with_base()
+ var lines =<< trim END
+ vim9script
+ def TwoArguments(str: string, nr: number)
+ echo str nr
+ enddef
+ var Ref = TwoArguments
+ Ref('a', 12)
+ 'b'->Ref(34)
+ END
+ v9.CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ def TwoArguments(str: string, nr: number)
+ echo str nr
+ enddef
+ var Ref = TwoArguments
+ 'a'->Ref('b')
+ END
+ v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 6)
+
+ lines =<< trim END
+ vim9script
+ def TwoArguments(str: string, nr: number)
+ echo str nr
+ enddef
+ var Ref = TwoArguments
+ 123->Ref(456)
+ END
+ v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
+
+ lines =<< trim END
+ vim9script
+ def TwoArguments(nr: number, str: string)
+ echo str nr
+ enddef
+ var Ref = TwoArguments
+ 123->Ref('b')
+ def AndNowCompiled()
+ 456->Ref('x')
+ enddef
+ AndNowCompiled()
+ END
+ v9.CheckScriptSuccess(lines)
enddef
def Test_closing_brace_at_start_of_line()
diff --git a/src/version.c b/src/version.c
index 1b7615c47..47eaf6b2a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -735,6 +735,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 5026,
+/**/
5025,
/**/
5024,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 496f4cde2..b7f590e10 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -3001,6 +3001,7 @@ compile_def_function(
* 0z1234->func() should not be confused with a zero line number
* "++nr" and "--nr" are eval commands
* in "$ENV->func()" the "$" is not a range
+ * "123->func()" is a method call
*/
cmd = ea.cmd;
if ((*cmd != '$' || starts_with_colon)
@@ -3008,7 +3009,8 @@ compile_def_function(
|| !(*cmd == '\''
|| (cmd[0] == '0' && cmd[1] == 'z')
|| (cmd[0] != NUL && cmd[0] == cmd[1]
- && (*cmd == '+' || *cmd == '-')))))
+ && (*cmd == '+' || *cmd == '-'))
+ || number_method(cmd))))
{
ea.cmd = skip_range(ea.cmd, TRUE, NULL);
if (ea.cmd > cmd)
diff --git a/src/vim9type.c b/src/vim9type.c
index 436feda51..28b282865 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -244,48 +244,44 @@ alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
/*
* Get a function type, based on the return type "ret_type".
- * If "argcount" is -1 or 0 a predefined type can be used.
- * If "argcount" > 0 always create a new type, so that arguments can be added.
+ * "argcount" must be -1 or 0, a predefined type can be used.
*/
type_T *
get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
{
// recognize commonly used types
- if (argcount <= 0)
+ if (ret_type == &t_unknown || ret_type == NULL)
{
- if (ret_type == &t_unknown || ret_type == NULL)
- {
- // (argcount == 0) is not possible
- return &t_func_unknown;
- }
- if (ret_type == &t_void)
- {
- if (argcount == 0)
- return &t_func_0_void;
- else
- return &t_func_void;
- }
- if (ret_type == &t_any)
- {
- if (argcount == 0)
- return &t_func_0_any;
- else
- return &t_func_any;
- }
- if (ret_type == &t_number)
- {
- if (argcount == 0)
- return &t_func_0_number;
- else
- return &t_func_number;
- }
- if (ret_type == &t_string)
- {
- if (argcount == 0)
- return &t_func_0_string;
- else
- return &t_func_string;
- }
+ // (argcount == 0) is not possible
+ return &t_func_unknown;
+ }
+ if (ret_type == &t_void)
+ {
+ if (argcount == 0)
+ return &t_func_0_void;
+ else
+ return &t_func_void;
+ }
+ if (ret_type == &t_any)
+ {
+ if (argcount == 0)
+ return &t_func_0_any;
+ else
+ return &t_func_any;
+ }
+ if (ret_type == &t_number)
+ {
+ if (argcount == 0)
+ return &t_func_0_number;
+ else
+ return &t_func_number;
+ }
+ if (ret_type == &t_string)
+ {
+ if (argcount == 0)
+ return &t_func_0_string;
+ else
+ return &t_func_string;
}
return alloc_func_type(ret_type, argcount, type_gap);
@@ -541,7 +537,7 @@ typval2type_vimvar(typval_T *tv, garray_T *type_gap)
{
if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
return &t_list_string;
- if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
+ if (tv->v_type == VAR_DICT) // e.g. for v:event
return &t_dict_any;
return typval2type(tv, get_copyID(), type_gap, TVTT_DO_MEMBER);
}
@@ -1441,6 +1437,7 @@ vartype_name(vartype_T type)
type_name(type_T *type, char **tofree)
{
char *name;
+ char *arg_free = NULL;
*tofree = NULL;
if (type == NULL)
@@ -1469,13 +1466,12 @@ type_name(type_T *type, char **tofree)
ga_init2(&ga, 1, 100);
if (ga_grow(&ga, 20) == FAIL)
- return "[unknown]";
+ goto failed;
STRCPY(ga.ga_data, "func(");
ga.ga_len += 5;
for (i = 0; i < type->tt_argcount; ++i)
{
- char *arg_free = NULL;
char *arg_type;
int len;
@@ -1490,17 +1486,13 @@ type_name(type_T *type, char **tofree)
}
len = (int)STRLEN(arg_type);
if (ga_grow(&ga, len + 8) == FAIL)
- {
- vim_free(arg_free);
- ga_clear(&ga);
- return "[unknown]";
- }
+ goto failed;
if (varargs && i == type->tt_argcount - 1)
ga_concat(&ga, (char_u *)"...");
else if (i >= type->tt_min_argcount)
*((char *)ga.ga_data + ga.ga_len++) = '?';
ga_concat(&ga, (char_u *)arg_type);
- vim_free(arg_free);
+ VIM_CLEAR(arg_free);
}
if (type->tt_argcount < 0)
// any number of arguments
@@ -1516,17 +1508,18 @@ type_name(type_T *type, char **tofree)
len = (int)STRLEN(ret_name) + 4;
if (ga_grow(&ga, len) == FAIL)
- {
- vim_free(ret_free);
- ga_clear(&ga);
- return "[unknown]";
- }
+ goto failed;
STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
vim_free(ret_free);
}
*tofree = ga.ga_data;
return ga.ga_data;
+
+failed:
+ vim_free(arg_free);
+ ga_clear(&ga);
+ return "[unknown]";
}
return name;