changeset 33466:3de472480e91 v9.0.1986

patch 9.0.1986: Vim9: accepting type-annotations Commit: https://github.com/vim/vim/commit/b5a0719cb7abf51b0540df527cb9738a3ccf0d37 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Thu Oct 5 20:14:43 2023 +0200 patch 9.0.1986: Vim9: accepting type-annotations Problem: Vim9: accepting type-annotations Solution: Reject type annotations outside of declarations. closes: #13267 closes: #13283 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Thu, 05 Oct 2023 20:30:08 +0200
parents 16445e83c2fd
children dcc13185c466
files src/eval.c src/evalvars.c src/testdir/test_vim9_assign.vim src/version.c src/vim.h src/vim9compile.c
diffstat 6 files changed, 55 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -1271,6 +1271,14 @@ get_lval(
 		    semsg(_(e_using_type_not_in_script_context_str), p);
 		    return NULL;
 		}
+		if (vim9script && (flags & GLV_NO_DECL) &&
+			!(flags & GLV_FOR_LOOP))
+		{
+		    // Using a type and not in a "var" declaration.
+		    semsg(_(e_trailing_characters_str), p);
+		    return NULL;
+		}
+
 
 		// parse the type after the name
 		lp->ll_type = parse_type(&tp,
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1858,6 +1858,7 @@ ex_let_one(
 	char_u	*p;
 	int	lval_flags = (flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
 							     ? GLV_NO_DECL : 0;
+	lval_flags |= (flags & ASSIGN_FOR_LOOP) ? GLV_FOR_LOOP : 0;
 	if (op != NULL && *op != '=')
 	    lval_flags |= GLV_ASSIGN_WITH_OP;
 
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -2822,6 +2822,45 @@ def Test_using_s_var_in_function()
   v9.CheckScriptSuccess(lines)
 enddef
 
+" Test for specifying a type in assignment
+def Test_type_specification_in_assignment()
+  # specify type for an existing script local variable without "var"
+  var lines =<< trim END
+    vim9script
+    var n: number = 10
+    n: number = 20
+  END
+  v9.CheckSourceFailure(lines, 'E488: Trailing characters: : number = 20', 3)
+
+  # specify type for a non-existing script local variable without "var"
+  lines =<< trim END
+    vim9script
+    MyVar: string = 'abc'
+  END
+  v9.CheckSourceFailure(lines, "E492: Not an editor command: MyVar: string = 'abc'", 2)
+
+  # specify type for an existing def local variable without "var"
+  lines =<< trim END
+    vim9script
+    def Foo()
+      var n: number = 10
+      n: number = 20
+    enddef
+    Foo()
+  END
+  v9.CheckSourceFailure(lines, 'E488: Trailing characters: : number = 20', 2)
+
+  # specify type for a non-existing def local variable without "var"
+  lines =<< trim END
+    vim9script
+    def Foo()
+      MyVar: string = 'abc'
+    enddef
+    Foo()
+  END
+  v9.CheckSourceFailure(lines, "E476: Invalid command: MyVar: string = 'abc'", 1)
+enddef
+
 let g:someVar = 'X'
 
 " Test for heredoc with Vim expressions.
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1986,
+/**/
     1985,
 /**/
     1984,
--- a/src/vim.h
+++ b/src/vim.h
@@ -2776,6 +2776,7 @@ typedef int (*opt_expand_cb_T)(optexpand
 #define GLV_COMPILING	TFN_COMPILING	// variable may be defined later
 #define GLV_ASSIGN_WITH_OP TFN_ASSIGN_WITH_OP // assignment with operator
 #define GLV_PREFER_FUNC	0x10000		// prefer function above variable
+#define GLV_FOR_LOOP	0x20000		// assigning to a loop variable
 
 #define DO_NOT_FREE_CNT 99999	// refcount for dict or list that should not
 				// be freed.
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1737,11 +1737,14 @@ compile_lhs(
 		if (is_decl)
 		{
 		    // if we come here with what looks like an assignment like
-		    // .= but which has been reject by assignment_len() from
+		    // .= but which has been rejected by assignment_len() from
 		    // may_compile_assignment give a better error message
 		    char_u *p = skipwhite(lhs->lhs_end);
 		    if (p[0] == '.' && p[1] == '=')
 			emsg(_(e_dot_equal_not_supported_with_script_version_two));
+		    else if (p[0] == ':')
+			// type specified in a non-var assignment
+			semsg(_(e_trailing_characters_str), p);
 		    else
 			semsg(_(e_variable_already_declared_str), lhs->lhs_name);
 		    return FAIL;