mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.0.1887: Vim9: class members are accessible via object
Problem: Vim9: class members are accessible via object Solution: Disable class member variable access using an object Class methods can be accessed only using the class name and cannot be accessed using an object. To be consistent with this, do the same for class member variables also. They can be accessed only using the class name and not using an object. closes: #13057 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
committed by
Christian Brabandt
parent
ee17b6f70d
commit
23c92d93c1
@@ -1955,10 +1955,6 @@ def Test_class_implements_interface()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
def F1(i: I1): list<number>
|
||||
return [ i.svar1, i.svar2 ]
|
||||
enddef
|
||||
|
||||
def F2(i: I1): list<number>
|
||||
return [ i.mvar1, i.mvar2 ]
|
||||
enddef
|
||||
@@ -1967,10 +1963,6 @@ def Test_class_implements_interface()
|
||||
var ob = B.new()
|
||||
var oc = C.new()
|
||||
|
||||
assert_equal([11, 12], F1(oa))
|
||||
assert_equal([21, 22], F1(ob))
|
||||
assert_equal([31, 32], F1(oc))
|
||||
|
||||
assert_equal([111, 112], F2(oa))
|
||||
assert_equal([121, 122], F2(ob))
|
||||
assert_equal([131, 132], F2(oc))
|
||||
@@ -2041,39 +2033,21 @@ def Test_class_implements_interface()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
def F1(i: I1): list<number>
|
||||
return [ i.svar1, i.svar2 ]
|
||||
enddef
|
||||
|
||||
def F2(i: I1): list<number>
|
||||
return [ i.mvar1, i.mvar2 ]
|
||||
enddef
|
||||
|
||||
def F3(i: I2): list<number>
|
||||
return [ i.svar3, i.svar4 ]
|
||||
enddef
|
||||
|
||||
def F4(i: I2): list<number>
|
||||
return [ i.mvar3, i.mvar4 ]
|
||||
enddef
|
||||
|
||||
def F5(o: C): number
|
||||
return o.svar5
|
||||
enddef
|
||||
|
||||
var oa = A.new()
|
||||
var ob = B.new()
|
||||
var oc = C.new()
|
||||
|
||||
assert_equal([[11, 12]], [F1(oa)])
|
||||
assert_equal([[21, 22], [23, 24]], [F1(ob), F3(ob)])
|
||||
assert_equal([[31, 32], [33, 34]], [F1(oc), F3(oc)])
|
||||
|
||||
assert_equal([[111, 112]], [F2(oa)])
|
||||
assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
|
||||
assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
|
||||
|
||||
assert_equal(1001, F5(oc))
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
enddef
|
||||
@@ -4182,25 +4156,7 @@ def Test_static_member_access_outside_class()
|
||||
return 11
|
||||
enddef
|
||||
|
||||
# access the class static through an interface argument
|
||||
def F2(i: I): number
|
||||
assert_equal(1, i.s_var1)
|
||||
assert_equal(2, i.s_var2)
|
||||
return 22
|
||||
enddef
|
||||
|
||||
# access the class static through an object interface
|
||||
def F3(o: C): number
|
||||
assert_equal(1, o.s_var1)
|
||||
assert_equal(2, o.s_var2)
|
||||
assert_equal(7, o.x_static)
|
||||
return 33
|
||||
enddef
|
||||
|
||||
assert_equal(11, F1())
|
||||
var c = C.new()
|
||||
assert_equal(22, F2(c))
|
||||
assert_equal(33, F3(c))
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
enddef
|
||||
@@ -4250,7 +4206,7 @@ def Test_private_member_access_outside_class()
|
||||
enddef
|
||||
T()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
|
||||
v9.CheckScriptFailure(lines, 'E1326: Member not found on object "A": _val')
|
||||
|
||||
# private static member variable
|
||||
lines =<< trim END
|
||||
@@ -4362,7 +4318,7 @@ def Test_modify_class_member_from_def_function()
|
||||
enddef
|
||||
|
||||
" Test for accessing a class member variable using an object
|
||||
def Test_class_member_access_using_object()
|
||||
def Test_class_variable_access_using_object()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
@@ -4374,26 +4330,74 @@ def Test_class_member_access_using_object()
|
||||
A.svar2->add(4)
|
||||
assert_equal([1, 3], A.svar1)
|
||||
assert_equal([2, 4], A.svar2)
|
||||
var a1 = A.new()
|
||||
a1.svar1->add(5)
|
||||
a1.svar2->add(6)
|
||||
assert_equal([1, 3, 5], a1.svar1)
|
||||
assert_equal([2, 4, 6], a1.svar2)
|
||||
|
||||
def Foo()
|
||||
A.svar1->add(7)
|
||||
A.svar2->add(8)
|
||||
assert_equal([1, 3, 5, 7], A.svar1)
|
||||
assert_equal([2, 4, 6, 8], A.svar2)
|
||||
var a2 = A.new()
|
||||
a2.svar1->add(9)
|
||||
a2.svar2->add(10)
|
||||
assert_equal([1, 3, 5, 7, 9], a2.svar1)
|
||||
assert_equal([2, 4, 6, 8, 10], a2.svar2)
|
||||
assert_equal([1, 3, 7], A.svar1)
|
||||
assert_equal([2, 4, 8], A.svar2)
|
||||
enddef
|
||||
Foo()
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Cannot read from a class variable using an object in script context
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
public this.var1: number
|
||||
public static svar2: list<number> = [1]
|
||||
endclass
|
||||
|
||||
var a = A.new()
|
||||
echo a.svar2
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1326: Member not found on object "A": svar2')
|
||||
|
||||
# Cannot write to a class variable using an object in script context
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
public this.var1: number
|
||||
public static svar2: list<number> = [1]
|
||||
endclass
|
||||
|
||||
var a = A.new()
|
||||
a.svar2 = [2]
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1334: Object member not found: svar2 = [2]')
|
||||
|
||||
# Cannot read from a class variable using an object in def method context
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
public this.var1: number
|
||||
public static svar2: list<number> = [1]
|
||||
endclass
|
||||
|
||||
def T()
|
||||
var a = A.new()
|
||||
echo a.svar2
|
||||
enddef
|
||||
T()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1326: Member not found on object "A": svar2')
|
||||
|
||||
# Cannot write to a class variable using an object in def method context
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
public this.var1: number
|
||||
public static svar2: list<number> = [1]
|
||||
endclass
|
||||
|
||||
def T()
|
||||
var a = A.new()
|
||||
a.svar2 = [2]
|
||||
enddef
|
||||
T()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1089: Unknown variable: svar2 = [2]')
|
||||
enddef
|
||||
|
||||
" Test for using a interface method using a child object
|
||||
|
@@ -699,6 +699,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1887,
|
||||
/**/
|
||||
1886,
|
||||
/**/
|
||||
|
@@ -1966,8 +1966,7 @@ class_object_index(
|
||||
{
|
||||
// Search in the object member variable table and the class member
|
||||
// variable table.
|
||||
if (get_member_tv(cl, TRUE, name, len, rettv) == OK
|
||||
|| get_member_tv(cl, FALSE, name, len, rettv) == OK)
|
||||
if (get_member_tv(cl, TRUE, name, len, rettv) == OK)
|
||||
{
|
||||
*arg = name_end;
|
||||
return OK;
|
||||
|
@@ -413,24 +413,6 @@ compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type)
|
||||
}
|
||||
}
|
||||
|
||||
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 (*name == '_' && !inside_class(cctx, cl))
|
||||
{
|
||||
semsg(_(e_cannot_access_private_member_str), m->ocm_name);
|
||||
return FAIL;
|
||||
}
|
||||
*arg = name_end;
|
||||
if (cl->class_flags & (CLASS_INTERFACE | CLASS_EXTENDED))
|
||||
return generate_GET_ITF_MEMBER(cctx, cl, i, m->ocm_type,
|
||||
TRUE);
|
||||
return generate_GET_OBJ_MEMBER(cctx, i, m->ocm_type, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Could be a function reference: "obj.Func".
|
||||
for (int i = 0; i < cl->class_obj_method_count; ++i)
|
||||
{
|
||||
|
Reference in New Issue
Block a user