]> granicus.if.org Git - vim/commitdiff
patch 9.0.1127: no error if function argument shadows class member v9.0.1127
authorBram Moolenaar <Bram@vim.org>
Sun, 1 Jan 2023 19:53:30 +0000 (19:53 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 1 Jan 2023 19:53:30 +0000 (19:53 +0000)
Problem:    No error if function argument shadows class member.
Solution:   Give an error for shadowing a class member.

src/proto/vim9class.pro
src/testdir/test_vim9_class.vim
src/version.c
src/vim9class.c
src/vim9compile.c
src/vim9expr.c

index edbddd267bbba2a4094808871ce3dbfef716b45e..66c6107a1accfe2867d79e06fe7a80228da062e3 100644 (file)
@@ -6,7 +6,7 @@ void ex_enum(exarg_T *eap);
 void ex_type(exarg_T *eap);
 int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
 ufunc_T *find_class_func(char_u **arg);
-int class_member_exists(char_u *name, class_T **cl_ret, int *idx_ret, cctx_T *cctx);
+int class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx);
 void copy_object(typval_T *from, typval_T *to);
 void object_unref(object_T *obj);
 void copy_class(typval_T *from, typval_T *to);
index 9dd6f83942fb22dbf0a61a4ac4dff832070a0361..8cb9113384f5023e6cd5f8eba8e16a3aac8f2246 100644 (file)
@@ -367,7 +367,8 @@ def Test_class_object_member_access()
   v9.CheckScriptFailure(lines, 'E1041:')
 enddef
 
-def Test_class_member_access()
+def Test_class_member()
+  # check access rules
   var lines =<< trim END
       vim9script
       class TextPos
@@ -401,6 +402,38 @@ def Test_class_member_access()
       assert_equal(17, TextPos.anybody)
   END
   v9.CheckScriptSuccess(lines)
+
+  # check shadowing
+  lines =<< trim END
+      vim9script
+
+      class Some
+        static count = 0
+        def Method(count: number)
+          echo count
+        enddef
+      endclass
+
+      var s = Some.new()
+      s.Method(7)
+  END
+  v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
+
+  lines =<< trim END
+      vim9script
+
+      class Some
+        static count = 0
+        def Method(arg: number)
+          var count = 3
+          echo arg count
+        enddef
+      endclass
+
+      var s = Some.new()
+      s.Method(7)
+  END
+  v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
 enddef
 
 def Test_class_function()
index 389209aae39335289d5f4548fd64181c0e0952ed..dc320bef6fc17a9c2896e40414652f15de11afeb 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1127,
 /**/
     1126,
 /**/
index b05dea8eff3931bcb76463639caf25c8774852a2..8e05a17f4c2a6067425fdc38bfda67f97ac51f84 100644 (file)
@@ -358,17 +358,19 @@ ex_class(exarg_T *eap)
            ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
            ga_clear_strings(&lines_to_free);
 
-           // TODO: how about errors?
-           int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
-           garray_T *fgap = has_static || is_new
-                                              ? &classfunctions : &objmethods;
-           if (uf != NULL && ga_grow(fgap, 1) == OK)
+           if (uf != NULL)
            {
-               if (is_new)
-                   uf->uf_flags |= FC_NEW;
+               int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
+               garray_T *fgap = has_static || is_new
+                                              ? &classfunctions : &objmethods;
+               if (ga_grow(fgap, 1) == OK)
+               {
+                   if (is_new)
+                       uf->uf_flags |= FC_NEW;
 
-               ((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
-               ++fgap->ga_len;
+                   ((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
+                   ++fgap->ga_len;
+               }
            }
        }
 
@@ -863,32 +865,30 @@ fail_after_eval:
 }
 
 /*
- * If "cctx->ctx_ufunc" indicates we are in a class, check if "name" is a class
- * member.  If it is then return TRUE and set "cl_ret" and "idx_ret".
+ * If "name[len]" is a class member in cctx->ctx_ufunc->uf_class return the
+ * index in class.class_class_members[].
+ * If "cl_ret" is not NULL set it to the class.
+ * Otherwise return -1;
  */
     int
-class_member_exists(
-       char_u  *name,
-       class_T **cl_ret,
-       int     *idx_ret,
-       cctx_T  *cctx)
+class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx)
 {
-    if (cctx->ctx_ufunc == NULL || cctx->ctx_ufunc->uf_class == NULL)
-       return FALSE;
+    if (cctx == NULL || cctx->ctx_ufunc == NULL
+                                         || cctx->ctx_ufunc->uf_class == NULL)
+       return -1;
     class_T *cl = cctx->ctx_ufunc->uf_class;
 
-    for (int idx = 0; idx < cl->class_class_member_count; ++idx)
+    for (int i = 0; i < cl->class_class_member_count; ++i)
     {
-       ocmember_T *m = &cl->class_class_members[idx];
-       if (STRCMP(m->ocm_name, name) == 0)
+       ocmember_T *m = &cl->class_class_members[i];
+       if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
        {
-           *cl_ret = cl;
-           *idx_ret = idx;
-           return TRUE;
+           if (cl_ret != NULL)
+               *cl_ret = cl;
+           return i;
        }
     }
-
-    return FALSE;
+    return -1;
 }
 
 /*
index 0d980ba4e249e9c514cf56ef6ed6f6e738dd23a0..0e6c32cbf7dd5feb225d337ee5855ea166f89347 100644 (file)
@@ -301,28 +301,6 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
     return FAIL;
 }
 
-/*
- * If "name" is a class member in cctx->ctx_ufunc->uf_class return the index in
- * class.class_class_members[].
- * Otherwise return -1;
- */
-    static int
-class_member_index(char_u *name, size_t len, cctx_T *cctx)
-{
-    if (cctx == NULL || cctx->ctx_ufunc == NULL
-                                         || cctx->ctx_ufunc->uf_class == NULL)
-       return -1;
-    class_T *cl = cctx->ctx_ufunc->uf_class;
-    for (int i = 0; i < cl->class_class_member_count; ++i)
-    {
-       ocmember_T *m = &cl->class_class_members[i];
-       if (STRNCMP(name, m->ocm_name, len) == 0
-               && m->ocm_name[len] == NUL)
-           return i;
-    }
-    return -1;
-}
-
 /*
  * Return TRUE if "name" is a local variable, argument, script variable or
  * imported.
@@ -338,7 +316,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
                        && (cctx->ctx_ufunc->uf_flags & FC_OBJECT)
                        && STRNCMP(name, "this", 4) == 0)))
            || script_var_exists(name, len, cctx, NULL) == OK
-           || class_member_index(name, len, cctx) >= 0
+           || class_member_index(name, len, NULL, cctx) >= 0
            || find_imported(name, len, FALSE) != NULL;
 }
 
@@ -376,9 +354,6 @@ check_defined(
     if (len == 1 && *p == '_')
        return OK;
 
-    if (class_member_index(p, len, cctx) >= 0)
-       return OK;
-
     if (script_var_exists(p, len, cctx, cstack) == OK)
     {
        if (is_arg)
@@ -388,6 +363,15 @@ check_defined(
        return FAIL;
     }
 
+    if (class_member_index(p, len, NULL, cctx) >= 0)
+    {
+       if (is_arg)
+           semsg(_(e_argument_already_declared_in_class_str), p);
+       else
+           semsg(_(e_variable_already_declared_in_class_str), p);
+       return FAIL;
+    }
+
     p[len] = NUL;
     if ((cctx != NULL
                && (lookup_local(p, len, NULL, cctx) == OK
@@ -1592,8 +1576,14 @@ compile_lhs(
                }
            }
            else if ((lhs->lhs_classmember_idx = class_member_index(
-                                      var_start, lhs->lhs_varlen, cctx)) >= 0)
+                                var_start, lhs->lhs_varlen, NULL, cctx)) >= 0)
            {
+               if (is_decl)
+               {
+                   semsg(_(e_variable_already_declared_in_class_str),
+                                                               lhs->lhs_name);
+                   return FAIL;
+               }
                lhs->lhs_dest = dest_class_member;
                lhs->lhs_class = cctx->ctx_ufunc->uf_class;
            }
@@ -2264,7 +2254,7 @@ compile_assignment(
     CLEAR_FIELD(lhs);
     long       start_lnum = SOURCING_LNUM;
 
-    int                has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
+    int        has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
     if (has_arg_is_set_prefix)
     {
        arg += 11;
index 463e79cbe4dffac85df352e1416e7539f3aa5b4e..4a3527f05755cac0084c59971024640aa753c2e7 100644 (file)
@@ -603,7 +603,7 @@ compile_load(
                else
                    gen_load = TRUE;
            }
-           else if (class_member_exists(name, &cl, &idx, cctx))
+           else if ((idx = class_member_index(*arg, len, &cl, cctx)) >= 0)
            {
                res = generate_CLASSMEMBER(cctx, TRUE, cl, idx);
            }