0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 9.0.1838: Vim9: Cannot modify class member vars from def function

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>
This commit is contained in:
Yegappan Lakshmanan
2023-09-01 22:05:45 +02:00
committed by Christian Brabandt
parent b147d31489
commit 3775f777a6
7 changed files with 77 additions and 24 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -699,6 +699,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1838,
/**/
1837,
/**/

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
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;

View File

@@ -438,8 +438,15 @@ 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)
{
*arg = name_end;