changeset 19872:8a7bede7b138 v8.2.0492

patch 8.2.0492: Vim9: some error messages not tested Commit: https://github.com/vim/vim/commit/a8c1770469504ae66c80bbdb03b6b31641215848 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Apr 1 21:17:24 2020 +0200 patch 8.2.0492: Vim9: some error messages not tested Problem: Vim9: some error messages not tested. Solution: Add more tests. Remove dead code. Fix uncovered bugs.
author Bram Moolenaar <Bram@vim.org>
date Wed, 01 Apr 2020 21:30:03 +0200
parents 7f8a267721e4
children b256cdad1dbf
files src/testdir/test_vim9_expr.vim src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c src/vim9execute.c
diffstat 5 files changed, 66 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -106,6 +106,8 @@ func Test_expr2_fails()
   call CheckDefFailure("let x = 1||2", msg)
   call CheckDefFailure("let x = 1 ||2", msg)
   call CheckDefFailure("let x = 1|| 2", msg)
+
+  call CheckDefFailure("let x = 1 || xxx", 'E1001:')
 endfunc
 
 " test &&
@@ -877,7 +879,7 @@ func Test_expr7_fails()
   call CheckDefFailure("let x = 123->{x -> x + 5) }", "E451:")
 
   call CheckDefFailure("let x = &notexist", 'E113:')
-  call CheckDefExecFailure("&grepprg = [343]", 'E1051:')
+  call CheckDefFailure("&grepprg = [343]", 'E1013:')
 
   call CheckDefExecFailure("echo s:doesnt_exist", 'E121:')
   call CheckDefExecFailure("echo g:doesnt_exist", 'E121:')
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -31,6 +31,8 @@ endfunc
 let s:appendToMe = 'xxx'
 let s:addToMe = 111
 let g:existing = 'yes'
+let g:inc_counter = 1
+let $SOME_ENV_VAR = 'some'
 
 def Test_assignment()
   let bool1: bool = true
@@ -94,6 +96,27 @@ def Test_assignment()
   assert_equal(333, s:addToMe)
   s:newVar = 'new'
   assert_equal('new', s:newVar)
+
+  set ts=7
+  &ts += 1
+  assert_equal(8, &ts)
+  call CheckDefFailure(['&notex += 3'], 'E113:')
+  call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
+  call CheckDefFailure(['&path += 3'], 'E1013:')
+
+  g:inc_counter += 1
+  assert_equal(2, g:inc_counter)
+
+  $SOME_ENV_VAR ..= 'more'
+  assert_equal('somemore', $SOME_ENV_VAR)
+  call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:')
+  call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:')
+
+  @a = 'areg'
+  @a ..= 'add'
+  assert_equal('aregadd', @a)
+  call CheckDefFailure(['@a += "more"'], 'E1013:')
+  call CheckDefFailure(['@a += 123'], 'E1013:')
 enddef
 
 func Test_assignment_failure()
--- 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 */
 /**/
+    492,
+/**/
     491,
 /**/
     490,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -277,6 +277,25 @@ get_dict_type(type_T *member_type, garra
     return type;
 }
 
+/*
+ * Return the type_T for a typval.  Only for primitive types.
+ */
+    static type_T *
+typval2type(typval_T *tv)
+{
+    if (tv->v_type == VAR_NUMBER)
+	return &t_number;
+    if (tv->v_type == VAR_BOOL)
+	return &t_bool;
+    if (tv->v_type == VAR_STRING)
+	return &t_string;
+    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
+	return &t_dict_any;
+    return &t_any;
+}
+
 /////////////////////////////////////////////////////////////////////
 // Following generate_ functions expect the caller to call ga_grow().
 
@@ -1402,7 +1421,7 @@ parse_type_member(char_u **arg, type_T *
 
 /*
  * Parse a type at "arg" and advance over it.
- * Return NULL for failure.
+ * Return &t_any for failure.
  */
     type_T *
 parse_type(char_u **arg, garray_T *type_list)
@@ -3462,7 +3481,7 @@ compile_assignment(char_u *arg, exarg_T 
     int		vimvaridx = -1;
     int		oplen = 0;
     int		heredoc = FALSE;
-    type_T	*type;
+    type_T	*type = &t_any;
     lvar_T	*lvar;
     char_u	*name;
     char_u	*sp;
@@ -3532,6 +3551,7 @@ compile_assignment(char_u *arg, exarg_T 
 	else if (*arg == '$')
 	{
 	    dest = dest_env;
+	    type = &t_string;
 	    if (is_decl)
 	    {
 		semsg(_("E1065: Cannot declare an environment variable: %s"), name);
@@ -3546,6 +3566,7 @@ compile_assignment(char_u *arg, exarg_T 
 		goto theend;
 	    }
 	    dest = dest_reg;
+	    type = &t_string;
 	    if (is_decl)
 	    {
 		semsg(_("E1066: Cannot declare a register: %s"), name);
@@ -3563,6 +3584,8 @@ compile_assignment(char_u *arg, exarg_T 
 	}
 	else if (STRNCMP(arg, "v:", 2) == 0)
 	{
+	    typval_T *vtv;
+
 	    vimvaridx = find_vim_var(name + 2);
 	    if (vimvaridx < 0)
 	    {
@@ -3570,6 +3593,8 @@ compile_assignment(char_u *arg, exarg_T 
 		goto theend;
 	    }
 	    dest = dest_vimvar;
+	    vtv = get_vim_var_tv(vimvaridx);
+	    type = typval2type(vtv);
 	    if (is_decl)
 	    {
 		semsg(_("E1064: Cannot declare a v: variable: %s"), name);
@@ -3625,16 +3650,9 @@ compile_assignment(char_u *arg, exarg_T 
 	    // parse optional type: "let var: type = expr"
 	    p = skipwhite(p + 1);
 	    type = parse_type(&p, cctx->ctx_type_list);
-	    if (type == NULL)
-		goto theend;
 	    has_type = TRUE;
 	}
-	else if (idx < 0)
-	{
-	    // global and new local default to "any" type
-	    type = &t_any;
-	}
-	else
+	else if (idx >= 0)
 	{
 	    lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
 	    type = lvar->lv_type;
@@ -3700,7 +3718,9 @@ compile_assignment(char_u *arg, exarg_T 
     }
     else if (oplen > 0)
     {
-	int r;
+	int	r;
+	type_T	*stacktype;
+	garray_T *stack;
 
 	// for "+=", "*=", "..=" etc. first load the current value
 	if (*op != '=')
@@ -3709,7 +3729,7 @@ compile_assignment(char_u *arg, exarg_T 
 	    {
 		case dest_option:
 		    // TODO: check the option exists
-		    generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type);
+		    generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
 		    break;
 		case dest_global:
 		    generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
@@ -3746,12 +3766,10 @@ compile_assignment(char_u *arg, exarg_T 
 	if (r == FAIL)
 	    goto theend;
 
+	stack = &cctx->ctx_type_stack;
+	stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
 	if (idx >= 0 && (is_decl || !has_type))
 	{
-	    garray_T	*stack = &cctx->ctx_type_stack;
-	    type_T	*stacktype =
-				((type_T **)stack->ga_data)[stack->ga_len - 1];
-
 	    lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
 	    if (!has_type)
 	    {
@@ -3767,6 +3785,8 @@ compile_assignment(char_u *arg, exarg_T 
 		if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL)
 		    goto theend;
 	}
+	else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
+	    goto theend;
     }
     else if (cmdidx == CMD_const)
     {
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -684,6 +684,8 @@ call_def_function(
 		    typval_T	optval;
 		    char_u	*name = iptr->isn_arg.string;
 
+		    // This is not expected to fail, name is checked during
+		    // compilation: don't set SOURCING_LNUM.
 		    if (ga_grow(&ectx.ec_stack, 1) == FAIL)
 			goto failed;
 		    if (get_option_tv(&name, &optval, TRUE) == FAIL)