changeset 33381:17301c641749 v9.0.1949

patch 9.0.1949: Vim9: allows reserved keywords as members Commit: https://github.com/vim/vim/commit/f057aca1cc2480e820b3ca5d8d407e3976369777 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Thu Sep 28 22:28:15 2023 +0200 patch 9.0.1949: Vim9: allows reserved keywords as members Problem: Vim9: allows reserved keywords as members Solution: Disallow reserved keywords, disallow duplicate object and class variables closes: #13209 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Thu, 28 Sep 2023 22:45:04 +0200
parents 7ba7c38a9914
children 0ca269de511d
files src/testdir/test_vim9_class.vim src/version.c src/vim9class.c
diffstat 3 files changed, 141 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -4150,7 +4150,7 @@ def Test_dup_member_variable()
     assert_equal(10, C.val)
     assert_equal(20, c.val)
   END
-  v9.CheckSourceSuccess(lines)
+  v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
 
   # Duplicate object member variable in a derived class
   lines =<< trim END
@@ -5768,4 +5768,91 @@ def Test_freed_object_from_previous_meth
   v9.CheckSourceSuccess(lines)
 enddef
 
+" Test for duplicate object and class variable
+def Test_duplicate_variable()
+  # Object variable name is same as the class variable name
+  var lines =<< trim END
+    vim9script
+    class A
+      public static sval: number
+      public this.sval: number
+    endclass
+    var a = A.new()
+  END
+  v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
+
+  # Duplicate variable name and calling a class method
+  lines =<< trim END
+    vim9script
+    class A
+      public static sval: number
+      public this.sval: number
+      def F1()
+        echo this.sval
+      enddef
+      static def F2()
+        echo sval
+      enddef
+    endclass
+    A.F2()
+  END
+  v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
+
+  # Duplicate variable with an empty constructor
+  lines =<< trim END
+    vim9script
+    class A
+      public static sval: number
+      public this.sval: number
+      def new()
+      enddef
+    endclass
+    var a = A.new()
+  END
+  v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
+enddef
+
+" Test for using a reserved keyword as a variable name
+def Test_reserved_varname()
+  for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
+                'null_function', 'null_list', 'null_partial', 'null_string',
+                'null_channel', 'null_job', 'super', 'this']
+
+    var lines =<< trim eval END
+      vim9script
+      class C
+        public this.{kword}: list<number> = [1, 2, 3]
+      endclass
+      var o = C.new()
+    END
+    v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
+
+    lines =<< trim eval END
+      vim9script
+      class C
+        public this.{kword}: list<number> = [1, 2, 3]
+        def new()
+        enddef
+      endclass
+      var o = C.new()
+    END
+    v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
+
+    lines =<< trim eval END
+      vim9script
+      class C
+        public this.{kword}: list<number> = [1, 2, 3]
+        def new()
+        enddef
+        def F()
+          echo this.{kword}
+        enddef
+      endclass
+      var o = C.new()
+      o.F()
+    END
+    v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
+  endfor
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1949,
+/**/
     1948,
 /**/
     1947,
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -893,24 +893,52 @@ check_func_arg_names(
 }
 
 /*
- * Returns TRUE if the member "varname" is already defined.
+ * Returns TRUE if 'varname' is a reserved keyword name
  */
     static int
-is_duplicate_member(garray_T *mgap, char_u *varname, char_u *varname_end)
+is_reserved_varname(char_u *varname, char_u *varname_end)
+{
+    int reserved = FALSE;
+    char_u save_varname_end = *varname_end;
+    *varname_end = NUL;
+
+    reserved = check_reserved_name(varname, FALSE) == FAIL;
+
+    *varname_end = save_varname_end;
+
+    return reserved;
+}
+
+/*
+ * Returns TRUE if the variable "varname" is already defined either as a class
+ * variable or as an object variable.
+ */
+    static int
+is_duplicate_variable(
+    garray_T	*class_members,
+    garray_T	*obj_members,
+    char_u	*varname,
+    char_u	*varname_end)
 {
     char_u	*name = vim_strnsave(varname, varname_end - varname);
     char_u	*pstr = (*name == '_') ? name + 1 : name;
     int		dup = FALSE;
 
-    for (int i = 0; i < mgap->ga_len; ++i)
+    for (int loop = 1; loop <= 2; loop++)
     {
-	ocmember_T *m = ((ocmember_T *)mgap->ga_data) + i;
-	char_u	*qstr = *m->ocm_name == '_' ? m->ocm_name + 1 : m->ocm_name;
-	if (STRCMP(pstr, qstr) == 0)
+	// loop == 1: class variables, loop == 2: object variables
+	garray_T    *vgap = (loop == 1) ? class_members : obj_members;
+	for (int i = 0; i < vgap->ga_len; ++i)
 	{
-	    semsg(_(e_duplicate_variable_str), name);
-	    dup = TRUE;
-	    break;
+	    ocmember_T *m = ((ocmember_T *)vgap->ga_data) + i;
+	    char_u	*qstr = *m->ocm_name == '_' ? m->ocm_name + 1
+						    : m->ocm_name;
+	    if (STRCMP(pstr, qstr) == 0)
+	    {
+		semsg(_(e_duplicate_variable_str), name);
+		dup = TRUE;
+		break;
+	    }
 	}
     }
 
@@ -1646,7 +1674,13 @@ early_ret:
 			  &varname_end, &type_list, &type,
 			  is_class ? &init_expr: NULL) == FAIL)
 		break;
-	    if (is_duplicate_member(&objmembers, varname, varname_end))
+	    if (is_reserved_varname(varname, varname_end))
+	    {
+		vim_free(init_expr);
+		break;
+	    }
+	    if (is_duplicate_variable(&classmembers, &objmembers, varname,
+								varname_end))
 	    {
 		vim_free(init_expr);
 		break;
@@ -1768,7 +1802,13 @@ early_ret:
 		      &varname_end, &type_list, &type,
 		      is_class ? &init_expr : NULL) == FAIL)
 		break;
-	    if (is_duplicate_member(&classmembers, varname, varname_end))
+	    if (is_reserved_varname(varname, varname_end))
+	    {
+		vim_free(init_expr);
+		break;
+	    }
+	    if (is_duplicate_variable(&classmembers, &objmembers, varname,
+								varname_end))
 	    {
 		vim_free(init_expr);
 		break;