summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2023-09-01 22:05:45 +0200
committerChristian Brabandt <cb@256bit.org>2023-09-01 22:05:45 +0200
commit3775f777a6add2a8d5060b40414e9c53062c8cd9 (patch)
treec6db91ae9aa6226189470956b435feadba9b56ad
parentb147d314897b7a82081644edf779e22138d44f2c (diff)
patch 9.0.1838: Vim9: Cannot modify class member vars from def functionv9.0.1838
Problem: Vim9: Cannot modify class member vars from def function Solution: Add support for modifying class member variables from a def function closes: #12995 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
-rw-r--r--src/proto/vim9class.pro2
-rw-r--r--src/testdir/test_vim9_class.vim24
-rw-r--r--src/version.c2
-rw-r--r--src/vim9class.c31
-rw-r--r--src/vim9compile.c8
-rw-r--r--src/vim9execute.c29
-rw-r--r--src/vim9expr.c7
7 files changed, 78 insertions, 25 deletions
diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro
index 47bfa9d1f5..5fa0ab2591 100644
--- a/src/proto/vim9class.pro
+++ b/src/proto/vim9class.pro
@@ -1,7 +1,7 @@
/* vim9class.c */
int object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl);
void ex_class(exarg_T *eap);
-type_T *class_member_type(class_T *cl, char_u *name, char_u *name_end, int *member_idx, ocmember_T **m);
+type_T *class_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx, ocmember_T **m);
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);
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 127531d28f..7ad53c763e 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -3783,4 +3783,28 @@ def Test_readonly_member_change_in_def_func()
v9.CheckScriptFailure(lines, 'E46: Cannot change read-only variable "val"')
enddef
+" Test for reading and writing a class member from a def function
+def Test_modify_class_member_from_def_function()
+ var lines =<< trim END
+ vim9script
+ class A
+ this.var1: number = 10
+ public static var2 = 20
+ public static var3 = 30
+ static _priv_var4: number = 40
+ endclass
+ def T()
+ assert_equal(20, A.var2)
+ assert_equal(30, A.var3)
+ A.var2 = 50
+ A.var3 = 60
+ assert_equal(50, A.var2)
+ assert_equal(60, A.var3)
+ assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
+ enddef
+ T()
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/version.c b/src/version.c
index d6c8ed14f3..512950a0ae 100644
--- 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 */
/**/
+ 1838,
+/**/
1837,
/**/
1836,
diff --git a/src/vim9class.c b/src/vim9class.c
index 0e780fafab..9c7badccb2 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -33,9 +33,9 @@ parse_member(
exarg_T *eap,
char_u *line,
char_u *varname,
- int has_public, // TRUE if "public" seen before "varname"
+ int has_public, // TRUE if "public" seen before "varname"
char_u **varname_end,
- garray_T *type_list,
+ garray_T *type_list,
type_T **type_ret,
char_u **init_expr)
{
@@ -119,12 +119,12 @@ parse_member(
*/
static int
add_member(
- garray_T *gap,
- char_u *varname,
- char_u *varname_end,
- int has_public,
- type_T *type,
- char_u *init_expr)
+ garray_T *gap,
+ char_u *varname,
+ char_u *varname_end,
+ int has_public,
+ type_T *type,
+ char_u *init_expr)
{
if (ga_grow(gap, 1) == FAIL)
return FAIL;
@@ -629,8 +629,8 @@ is_valid_constructor(ufunc_T *uf, int is_abstract, int has_static)
*/
static int
update_member_method_lookup_table(
- class_T *ifcl,
- class_T *cl,
+ class_T *ifcl,
+ class_T *cl,
garray_T *objmethods,
int pobj_method_offset,
int is_interface)
@@ -1553,12 +1553,15 @@ cleanup:
/*
* Find member "name" in class "cl", set "member_idx" to the member index and
* return its type.
+ * When "is_object" is TRUE, then look for object members. Otherwise look for
+ * class members.
* When not found "member_idx" is set to -1 and t_any is returned.
* Set *p_m ocmmember_T if not NULL
*/
type_T *
class_member_type(
class_T *cl,
+ int is_object,
char_u *name,
char_u *name_end,
int *member_idx,
@@ -1566,10 +1569,14 @@ class_member_type(
{
*member_idx = -1; // not found (yet)
size_t len = name_end - name;
+ int member_count = is_object ? cl->class_obj_member_count
+ : cl->class_class_member_count;
+ ocmember_T *members = is_object ? cl->class_obj_members
+ : cl->class_class_members;
- for (int i = 0; i < cl->class_obj_member_count; ++i)
+ for (int i = 0; i < member_count; ++i)
{
- ocmember_T *m = cl->class_obj_members + i;
+ ocmember_T *m = members + i;
if (STRNCMP(m->ocm_name, name, len) == 0 && m->ocm_name[len] == NUL)
{
*member_idx = i;
diff --git a/src/vim9compile.c b/src/vim9compile.c
index cc5a302a53..62528e9570 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1868,8 +1868,10 @@ compile_lhs(
class_T *cl = lhs->lhs_type->tt_class;
ocmember_T *m;
- lhs->lhs_member_type = class_member_type(cl, after + 1,
- lhs->lhs_end, &lhs->lhs_member_idx, &m);
+ lhs->lhs_member_type = class_member_type(cl,
+ lhs->lhs_type->tt_type == VAR_OBJECT,
+ after + 1, lhs->lhs_end,
+ &lhs->lhs_member_idx, &m);
if (lhs->lhs_member_idx < 0)
return FAIL;
@@ -2091,7 +2093,7 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
return FAIL;
class_T *cl = lhs->lhs_type->tt_class;
- type_T *type = class_member_type(cl, dot + 1,
+ type_T *type = class_member_type(cl, TRUE, dot + 1,
lhs->lhs_end, &lhs->lhs_member_idx,
NULL);
if (lhs->lhs_member_idx < 0)
diff --git a/src/vim9execute.c b/src/vim9execute.c
index b26934dc47..2fbce780f7 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -2144,7 +2144,7 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
// Stack contains:
// -3 value to be stored
// -2 index
- // -1 dict, list, blob or object
+ // -1 dict, list, blob, object or class
tv = STACK_TV_BOT(-3);
SOURCING_LNUM = iptr->isn_lnum;
@@ -2306,14 +2306,25 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
}
else if (dest_type == VAR_CLASS || dest_type == VAR_OBJECT)
{
- object_T *obj = tv_dest->vval.v_object;
- typval_T *otv = (typval_T *)(obj + 1);
-
- class_T *itf = iptr->isn_arg.storeindex.si_class;
- if (itf != NULL)
- // convert interface member index to class member index
- lidx = object_index_from_itf_index(itf, FALSE,
- lidx, obj->obj_class);
+ typval_T *otv;
+
+ if (dest_type == VAR_OBJECT)
+ {
+ object_T *obj = tv_dest->vval.v_object;
+
+ otv = (typval_T *)(obj + 1);
+ class_T *itf = iptr->isn_arg.storeindex.si_class;
+ if (itf != NULL)
+ // convert interface member index to class member index
+ lidx = object_index_from_itf_index(itf, FALSE,
+ lidx, obj->obj_class);
+ }
+ else
+ {
+ // VAR_CLASS
+ class_T *class = tv_dest->vval.v_class;
+ otv = class->class_members_tv;
+ }
clear_tv(&otv[lidx]);
otv[lidx] = *tv;
diff --git a/src/vim9expr.c b/src/vim9expr.c
index bfbb369715..e894969384 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -438,7 +438,14 @@ compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type)
{
ocmember_T *m = &cl->class_class_members[idx];
if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
+ {
+ if (*name == '_' && !inside_class(cctx, cl))
+ {
+ semsg(_(e_cannot_access_private_member_str), m->ocm_name);
+ return FAIL;
+ }
break;
+ }
}
if (idx < cl->class_class_member_count)
{