Patch 9.0.1127
Problem:    No error if function argument shadows class member.
Solution:   Give an error for shadowing a class member.
Files:      src/vim9expr.c, src/vim9class.c, src/proto/vim9class.pro,
            src/vim9compile.c, src/testdir/test_vim9_class.vim


*** ../vim-9.0.1126/src/vim9expr.c      2023-01-01 12:58:29.474417546 +0000
--- src/vim9expr.c      2023-01-01 18:59:31.950852320 +0000
***************
*** 603,609 ****
                else
                    gen_load = TRUE;
            }
!           else if (class_member_exists(name, &cl, &idx, cctx))
            {
                res = generate_CLASSMEMBER(cctx, TRUE, cl, idx);
            }
--- 603,609 ----
                else
                    gen_load = TRUE;
            }
!           else if ((idx = class_member_index(*arg, len, &cl, cctx)) >= 0)
            {
                res = generate_CLASSMEMBER(cctx, TRUE, cl, idx);
            }
*** ../vim-9.0.1126/src/vim9class.c     2023-01-01 14:11:23.358483466 +0000
--- src/vim9class.c     2023-01-01 19:17:18.623906933 +0000
***************
*** 358,374 ****
            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 (is_new)
!                   uf->uf_flags |= FC_NEW;
  
!               ((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
!               ++fgap->ga_len;
            }
        }
  
--- 358,376 ----
            ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
            ga_clear_strings(&lines_to_free);
  
!           if (uf != NULL)
            {
!               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;
!               }
            }
        }
  
***************
*** 863,894 ****
  }
  
  /*
!  * 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".
   */
      int
! class_member_exists(
!       char_u  *name,
!       class_T **cl_ret,
!       int     *idx_ret,
!       cctx_T  *cctx)
  {
!     if (cctx->ctx_ufunc == NULL || cctx->ctx_ufunc->uf_class == NULL)
!       return FALSE;
      class_T *cl = cctx->ctx_ufunc->uf_class;
  
!     for (int idx = 0; idx < cl->class_class_member_count; ++idx)
      {
!       ocmember_T *m = &cl->class_class_members[idx];
!       if (STRCMP(m->ocm_name, name) == 0)
        {
!           *cl_ret = cl;
!           *idx_ret = idx;
!           return TRUE;
        }
      }
! 
!     return FALSE;
  }
  
  /*
--- 865,894 ----
  }
  
  /*
!  * 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_index(char_u *name, size_t len, class_T **cl_ret, 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)
        {
!           if (cl_ret != NULL)
!               *cl_ret = cl;
!           return i;
        }
      }
!     return -1;
  }
  
  /*
*** ../vim-9.0.1126/src/proto/vim9class.pro     2023-01-01 12:58:29.470417543 
+0000
--- src/proto/vim9class.pro     2023-01-01 19:05:25.757452321 +0000
***************
*** 6,12 ****
  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);
  void copy_object(typval_T *from, typval_T *to);
  void object_unref(object_T *obj);
  void copy_class(typval_T *from, typval_T *to);
--- 6,12 ----
  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_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);
*** ../vim-9.0.1126/src/vim9compile.c   2022-12-29 20:56:20.021538298 +0000
--- src/vim9compile.c   2023-01-01 19:48:15.002633479 +0000
***************
*** 302,329 ****
  }
  
  /*
-  * 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.
   */
--- 302,307 ----
***************
*** 338,344 ****
                        && (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
            || find_imported(name, len, FALSE) != NULL;
  }
  
--- 316,322 ----
                        && (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, NULL, cctx) >= 0
            || find_imported(name, len, FALSE) != NULL;
  }
  
***************
*** 376,384 ****
      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)
--- 354,359 ----
***************
*** 388,393 ****
--- 363,377 ----
        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,1599 ****
                }
            }
            else if ((lhs->lhs_classmember_idx = class_member_index(
!                                      var_start, lhs->lhs_varlen, cctx)) >= 0)
            {
                lhs->lhs_dest = dest_class_member;
                lhs->lhs_class = cctx->ctx_ufunc->uf_class;
            }
--- 1576,1589 ----
                }
            }
            else if ((lhs->lhs_classmember_idx = class_member_index(
!                                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,2270 ****
      CLEAR_FIELD(lhs);
      long      start_lnum = SOURCING_LNUM;
  
!     int               has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) 
== 0;
      if (has_arg_is_set_prefix)
      {
        arg += 11;
--- 2254,2260 ----
      CLEAR_FIELD(lhs);
      long      start_lnum = SOURCING_LNUM;
  
!     int       has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
      if (has_arg_is_set_prefix)
      {
        arg += 11;
*** ../vim-9.0.1126/src/testdir/test_vim9_class.vim     2023-01-01 
12:58:29.474417546 +0000
--- src/testdir/test_vim9_class.vim     2023-01-01 19:50:20.110562669 +0000
***************
*** 367,373 ****
    v9.CheckScriptFailure(lines, 'E1041:')
  enddef
  
! def Test_class_member_access()
    var lines =<< trim END
        vim9script
        class TextPos
--- 367,374 ----
    v9.CheckScriptFailure(lines, 'E1041:')
  enddef
  
! def Test_class_member()
!   # check access rules
    var lines =<< trim END
        vim9script
        class TextPos
***************
*** 401,406 ****
--- 402,439 ----
        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()
*** ../vim-9.0.1126/src/version.c       2023-01-01 18:03:55.476613184 +0000
--- src/version.c       2023-01-01 19:51:20.590526047 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1127,
  /**/

-- 
INSPECTOR END OF FILM: Move along.  There's nothing to see!  Keep moving!
   [Suddenly he notices the cameras.]
INSPECTOR END OF FILM: (to Camera) All right, put that away sonny.
   [He walks over to it and puts his hand over the lens.]
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230101195411.026A81C0AA3%40moolenaar.net.

Raspunde prin e-mail lui