]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1949: Vim9: allows reserved keywords as members v9.0.1949
authorYegappan Lakshmanan <yegappan@yahoo.com>
Thu, 28 Sep 2023 20:28:15 +0000 (22:28 +0200)
committerChristian Brabandt <cb@256bit.org>
Thu, 28 Sep 2023 20:28:15 +0000 (22:28 +0200)
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>
src/testdir/test_vim9_class.vim
src/version.c
src/vim9class.c

index c272aab396e2d33bfa33570788a9ca216595af0d..681f614c9b6e1887c0efaf2627f09b1e449b86cd 100644 (file)
@@ -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_method_call()
   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
index 49b406781c3c1f20bfc0c22b13b297cd7aec7873..dade6d2fed8d3be4e81012b5c38169ebaa2fc963 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1949,
 /**/
     1948,
 /**/
index 8b07d76498db7ef0dd6e67717ee5bde448f11625..4c70f8d0fcf6e4de9b06024a59af505c53381f8d 100644 (file)
@@ -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;