Skip to content

Commit cf138d4

Browse files
erraelyegappan
authored andcommitted
patch 9.0.1880: Vim9: Need more tests for inheritance
Problem: Vim9: Need more tests for inheritance Solution: Add access tests and fixes. `inside_class` fix from yegappan. `object_index_from_itf_index` fix access of member on class extending class implementing interface. Based on tests from Vim9: Class/Object member variable access control #12979 closes: #13032 related: #12979 Signed-off-by: Christian Brabandt <[email protected]> Co-authored-by: Ernie Rael <[email protected]> Co-authored-by: Yegappan Lakshmanan <[email protected]>
1 parent f7ac0ef commit cf138d4

3 files changed

Lines changed: 281 additions & 5 deletions

File tree

src/testdir/test_vim9_class.vim

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,50 @@ def Test_class_object_member_access()
933933
endclass
934934
END
935935
v9.CheckScriptFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
936+
937+
# Access from child class extending a class:
938+
lines =<< trim END
939+
vim9script
940+
class A
941+
this.ro_obj_var = 10
942+
public this.rw_obj_var = 20
943+
this._priv_obj_var = 30
944+
945+
static ro_class_var = 40
946+
public static rw_class_var = 50
947+
static _priv_class_var = 60
948+
endclass
949+
950+
class B extends A
951+
def Foo()
952+
var x: number
953+
x = this.ro_obj_var
954+
this.ro_obj_var = 0
955+
x = this.rw_obj_var
956+
this.rw_obj_var = 0
957+
x = this._priv_obj_var
958+
this._priv_obj_var = 0
959+
960+
x = ro_class_var
961+
ro_class_var = 0
962+
x = rw_class_var
963+
rw_class_var = 0
964+
x = _priv_class_var
965+
_priv_class_var = 0
966+
967+
x = A.ro_class_var
968+
A.ro_class_var = 0
969+
x = A.rw_class_var
970+
A.rw_class_var = 0
971+
x = A._priv_class_var
972+
A._priv_class_var = 0
973+
enddef
974+
endclass
975+
976+
var b = B.new()
977+
b.Foo()
978+
END
979+
v9.CheckScriptSuccess(lines)
936980
enddef
937981

938982
def Test_class_object_compare()
@@ -1867,6 +1911,171 @@ def Test_class_implements_interface()
18671911
endclass
18681912
END
18691913
v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
1914+
1915+
# access superclass interface members from subclass, mix variable order
1916+
lines =<< trim END
1917+
vim9script
1918+
1919+
interface I1
1920+
public static svar1: number
1921+
public static svar2: number
1922+
public this.mvar1: number
1923+
public this.mvar2: number
1924+
endinterface
1925+
1926+
# NOTE: the order is swapped
1927+
class A implements I1
1928+
public this.mvar2: number
1929+
public this.mvar1: number
1930+
public static svar2: number
1931+
public static svar1: number
1932+
def new()
1933+
svar1 = 11
1934+
svar2 = 12
1935+
this.mvar1 = 111
1936+
this.mvar2 = 112
1937+
enddef
1938+
endclass
1939+
1940+
class B extends A
1941+
def new()
1942+
svar1 = 21
1943+
svar2 = 22
1944+
this.mvar1 = 121
1945+
this.mvar2 = 122
1946+
enddef
1947+
endclass
1948+
1949+
class C extends B
1950+
def new()
1951+
svar1 = 31
1952+
svar2 = 32
1953+
this.mvar1 = 131
1954+
this.mvar2 = 132
1955+
enddef
1956+
endclass
1957+
1958+
def F1(i: I1): list<number>
1959+
return [ i.svar1, i.svar2 ]
1960+
enddef
1961+
1962+
def F2(i: I1): list<number>
1963+
return [ i.mvar1, i.mvar2 ]
1964+
enddef
1965+
1966+
var oa = A.new()
1967+
var ob = B.new()
1968+
var oc = C.new()
1969+
1970+
assert_equal([11, 12], F1(oa))
1971+
assert_equal([21, 22], F1(ob))
1972+
assert_equal([31, 32], F1(oc))
1973+
1974+
assert_equal([111, 112], F2(oa))
1975+
assert_equal([121, 122], F2(ob))
1976+
assert_equal([131, 132], F2(oc))
1977+
END
1978+
v9.CheckScriptSuccess(lines)
1979+
1980+
# Access superclass interface members from subclass, mix variable order.
1981+
# Two interfaces, one on A, one on B; each has both kinds of variables
1982+
lines =<< trim END
1983+
vim9script
1984+
1985+
interface I1
1986+
public static svar1: number
1987+
public static svar2: number
1988+
public this.mvar1: number
1989+
public this.mvar2: number
1990+
endinterface
1991+
1992+
interface I2
1993+
public static svar3: number
1994+
public static svar4: number
1995+
public this.mvar3: number
1996+
public this.mvar4: number
1997+
endinterface
1998+
1999+
class A implements I1
2000+
public static svar1: number
2001+
public static svar2: number
2002+
public this.mvar1: number
2003+
public this.mvar2: number
2004+
def new()
2005+
svar1 = 11
2006+
svar2 = 12
2007+
this.mvar1 = 111
2008+
this.mvar2 = 112
2009+
enddef
2010+
endclass
2011+
2012+
class B extends A implements I2
2013+
public static svar3: number
2014+
public static svar4: number
2015+
public this.mvar3: number
2016+
public this.mvar4: number
2017+
def new()
2018+
svar1 = 21
2019+
svar2 = 22
2020+
svar3 = 23
2021+
svar4 = 24
2022+
this.mvar1 = 121
2023+
this.mvar2 = 122
2024+
this.mvar3 = 123
2025+
this.mvar4 = 124
2026+
enddef
2027+
endclass
2028+
2029+
class C extends B
2030+
public static svar5: number
2031+
def new()
2032+
svar1 = 31
2033+
svar2 = 32
2034+
svar3 = 33
2035+
svar4 = 34
2036+
svar5 = 1001
2037+
this.mvar1 = 131
2038+
this.mvar2 = 132
2039+
this.mvar3 = 133
2040+
this.mvar4 = 134
2041+
enddef
2042+
endclass
2043+
2044+
def F1(i: I1): list<number>
2045+
return [ i.svar1, i.svar2 ]
2046+
enddef
2047+
2048+
def F2(i: I1): list<number>
2049+
return [ i.mvar1, i.mvar2 ]
2050+
enddef
2051+
2052+
def F3(i: I2): list<number>
2053+
return [ i.svar3, i.svar4 ]
2054+
enddef
2055+
2056+
def F4(i: I2): list<number>
2057+
return [ i.mvar3, i.mvar4 ]
2058+
enddef
2059+
2060+
def F5(o: C): number
2061+
return o.svar5
2062+
enddef
2063+
2064+
var oa = A.new()
2065+
var ob = B.new()
2066+
var oc = C.new()
2067+
2068+
assert_equal([[11, 12]], [F1(oa)])
2069+
assert_equal([[21, 22], [23, 24]], [F1(ob), F3(ob)])
2070+
assert_equal([[31, 32], [33, 34]], [F1(oc), F3(oc)])
2071+
2072+
assert_equal([[111, 112]], [F2(oa)])
2073+
assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2074+
assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
2075+
2076+
assert_equal(1001, F5(oc))
2077+
END
2078+
v9.CheckScriptSuccess(lines)
18702079
enddef
18712080

18722081
def Test_call_interface_method()
@@ -3592,6 +3801,64 @@ def Test_objmethod_funcarg()
35923801
v9.CheckScriptSuccess(lines)
35933802
enddef
35943803

3804+
def Test_static_inheritence()
3805+
# subclasses get their own static copy
3806+
var lines =<< trim END
3807+
vim9script
3808+
3809+
class A
3810+
static _svar: number
3811+
this._mvar: number
3812+
def new()
3813+
_svar = 1
3814+
this._mvar = 101
3815+
enddef
3816+
def AccessObject(): number
3817+
return this._mvar
3818+
enddef
3819+
def AccessStaticThroughObject(): number
3820+
return _svar
3821+
enddef
3822+
endclass
3823+
3824+
class B extends A
3825+
def new()
3826+
_svar = 2
3827+
this._mvar = 102
3828+
enddef
3829+
endclass
3830+
3831+
class C extends B
3832+
def new()
3833+
_svar = 3
3834+
this._mvar = 103
3835+
enddef
3836+
3837+
def AccessPrivateStaticThroughClassName(): number
3838+
assert_equal(1, A._svar)
3839+
assert_equal(2, B._svar)
3840+
assert_equal(3, C._svar)
3841+
return 444
3842+
enddef
3843+
endclass
3844+
3845+
var oa = A.new()
3846+
var ob = B.new()
3847+
var oc = C.new()
3848+
assert_equal(101, oa.AccessObject())
3849+
assert_equal(102, ob.AccessObject())
3850+
assert_equal(103, oc.AccessObject())
3851+
3852+
assert_equal(444, oc.AccessPrivateStaticThroughClassName())
3853+
3854+
# verify object properly resolves to correct static
3855+
assert_equal(1, oa.AccessStaticThroughObject())
3856+
assert_equal(2, ob.AccessStaticThroughObject())
3857+
assert_equal(3, oc.AccessStaticThroughObject())
3858+
END
3859+
v9.CheckScriptSuccess(lines)
3860+
enddef
3861+
35953862
" Test for declaring duplicate object and class members
35963863
def Test_dup_member_variable()
35973864
# Duplicate member variable

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,8 @@ static char *(features[]) =
699699

700700
static int included_patches[] =
701701
{ /* Add new patch number below this line */
702+
/**/
703+
1880,
702704
/**/
703705
1879,
704706
/**/

src/vim9class.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,16 @@ object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl,
237237
if (cl == itf)
238238
return idx;
239239

240-
itf2class_T *i2c;
241-
for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
242-
if (i2c->i2c_class == cl && i2c->i2c_is_method == is_method)
243-
break;
240+
itf2class_T *i2c = NULL;
241+
int searching = TRUE;
242+
for (class_T *super = cl; super != NULL && searching;
243+
super = super->class_extends)
244+
for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
245+
if (i2c->i2c_class == super && i2c->i2c_is_method == is_method)
246+
{
247+
searching = FALSE;
248+
break;
249+
}
244250
if (i2c == NULL)
245251
{
246252
siemsg("class %s not found on interface %s",
@@ -1978,7 +1984,8 @@ class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx)
19781984
inside_class(cctx_T *cctx_arg, class_T *cl)
19791985
{
19801986
for (cctx_T *cctx = cctx_arg; cctx != NULL; cctx = cctx->ctx_outer)
1981-
if (cctx->ctx_ufunc != NULL && cctx->ctx_ufunc->uf_class == cl)
1987+
if (cctx->ctx_ufunc != NULL
1988+
&& class_instance_of(cctx->ctx_ufunc->uf_class, cl))
19821989
return TRUE;
19831990
return FALSE;
19841991
}

0 commit comments

Comments
 (0)