To: vim_dev@googlegroups.com Subject: Patch 9.0.1127 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///