summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErnie Rael <errael@raelity.com>2023-09-06 20:45:03 +0200
committerChristian Brabandt <cb@256bit.org>2023-09-06 20:45:03 +0200
commitcf138d4ea5b7e4495abbc867f9bb8a6be6482762 (patch)
tree816ed9323e5126d85e15149234ec76fb17bfb553
parentf7ac0ef5098856bedca26e7073594a407c05636f (diff)
patch 9.0.1880: Vim9: Need more tests for inheritancev9.0.1880
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 <cb@256bit.org> Co-authored-by: Ernie Rael <errael@raelity.com> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
-rw-r--r--src/testdir/test_vim9_class.vim267
-rw-r--r--src/version.c2
-rw-r--r--src/vim9class.c17
3 files changed, 281 insertions, 5 deletions
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index bf8f649d6e..a6dd66bcc9 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -933,6 +933,50 @@ def Test_class_object_member_access()
endclass
END
v9.CheckScriptFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
+
+ # Access from child class extending a class:
+ lines =<< trim END
+ vim9script
+ class A
+ this.ro_obj_var = 10
+ public this.rw_obj_var = 20
+ this._priv_obj_var = 30
+
+ static ro_class_var = 40
+ public static rw_class_var = 50
+ static _priv_class_var = 60
+ endclass
+
+ class B extends A
+ def Foo()
+ var x: number
+ x = this.ro_obj_var
+ this.ro_obj_var = 0
+ x = this.rw_obj_var
+ this.rw_obj_var = 0
+ x = this._priv_obj_var
+ this._priv_obj_var = 0
+
+ x = ro_class_var
+ ro_class_var = 0
+ x = rw_class_var
+ rw_class_var = 0
+ x = _priv_class_var
+ _priv_class_var = 0
+
+ x = A.ro_class_var
+ A.ro_class_var = 0
+ x = A.rw_class_var
+ A.rw_class_var = 0
+ x = A._priv_class_var
+ A._priv_class_var = 0
+ enddef
+ endclass
+
+ var b = B.new()
+ b.Foo()
+ END
+ v9.CheckScriptSuccess(lines)
enddef
def Test_class_object_compare()
@@ -1867,6 +1911,171 @@ def Test_class_implements_interface()
endclass
END
v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
+
+ # access superclass interface members from subclass, mix variable order
+ lines =<< trim END
+ vim9script
+
+ interface I1
+ public static svar1: number
+ public static svar2: number
+ public this.mvar1: number
+ public this.mvar2: number
+ endinterface
+
+ # NOTE: the order is swapped
+ class A implements I1
+ public this.mvar2: number
+ public this.mvar1: number
+ public static svar2: number
+ public static svar1: number
+ def new()
+ svar1 = 11
+ svar2 = 12
+ this.mvar1 = 111
+ this.mvar2 = 112
+ enddef
+ endclass
+
+ class B extends A
+ def new()
+ svar1 = 21
+ svar2 = 22
+ this.mvar1 = 121
+ this.mvar2 = 122
+ enddef
+ endclass
+
+ class C extends B
+ def new()
+ svar1 = 31
+ svar2 = 32
+ this.mvar1 = 131
+ this.mvar2 = 132
+ 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
+
+ var oa = A.new()
+ 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))
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # Access superclass interface members from subclass, mix variable order.
+ # Two interfaces, one on A, one on B; each has both kinds of variables
+ lines =<< trim END
+ vim9script
+
+ interface I1
+ public static svar1: number
+ public static svar2: number
+ public this.mvar1: number
+ public this.mvar2: number
+ endinterface
+
+ interface I2
+ public static svar3: number
+ public static svar4: number
+ public this.mvar3: number
+ public this.mvar4: number
+ endinterface
+
+ class A implements I1
+ public static svar1: number
+ public static svar2: number
+ public this.mvar1: number
+ public this.mvar2: number
+ def new()
+ svar1 = 11
+ svar2 = 12
+ this.mvar1 = 111
+ this.mvar2 = 112
+ enddef
+ endclass
+
+ class B extends A implements I2
+ public static svar3: number
+ public static svar4: number
+ public this.mvar3: number
+ public this.mvar4: number
+ def new()
+ svar1 = 21
+ svar2 = 22
+ svar3 = 23
+ svar4 = 24
+ this.mvar1 = 121
+ this.mvar2 = 122
+ this.mvar3 = 123
+ this.mvar4 = 124
+ enddef
+ endclass
+
+ class C extends B
+ public static svar5: number
+ def new()
+ svar1 = 31
+ svar2 = 32
+ svar3 = 33
+ svar4 = 34
+ svar5 = 1001
+ this.mvar1 = 131
+ this.mvar2 = 132
+ this.mvar3 = 133
+ this.mvar4 = 134
+ 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
def Test_call_interface_method()
@@ -3592,6 +3801,64 @@ def Test_objmethod_funcarg()
v9.CheckScriptSuccess(lines)
enddef
+def Test_static_inheritence()
+ # subclasses get their own static copy
+ var lines =<< trim END
+ vim9script
+
+ class A
+ static _svar: number
+ this._mvar: number
+ def new()
+ _svar = 1
+ this._mvar = 101
+ enddef
+ def AccessObject(): number
+ return this._mvar
+ enddef
+ def AccessStaticThroughObject(): number
+ return _svar
+ enddef
+ endclass
+
+ class B extends A
+ def new()
+ _svar = 2
+ this._mvar = 102
+ enddef
+ endclass
+
+ class C extends B
+ def new()
+ _svar = 3
+ this._mvar = 103
+ enddef
+
+ def AccessPrivateStaticThroughClassName(): number
+ assert_equal(1, A._svar)
+ assert_equal(2, B._svar)
+ assert_equal(3, C._svar)
+ return 444
+ enddef
+ endclass
+
+ var oa = A.new()
+ var ob = B.new()
+ var oc = C.new()
+ assert_equal(101, oa.AccessObject())
+ assert_equal(102, ob.AccessObject())
+ assert_equal(103, oc.AccessObject())
+
+ assert_equal(444, oc.AccessPrivateStaticThroughClassName())
+
+ # verify object properly resolves to correct static
+ assert_equal(1, oa.AccessStaticThroughObject())
+ assert_equal(2, ob.AccessStaticThroughObject())
+ assert_equal(3, oc.AccessStaticThroughObject())
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
" Test for declaring duplicate object and class members
def Test_dup_member_variable()
# Duplicate member variable
diff --git a/src/version.c b/src/version.c
index 4703b42911..a3d6ed0ef5 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 */
/**/
+ 1880,
+/**/
1879,
/**/
1878,
diff --git a/src/vim9class.c b/src/vim9class.c
index cc4410d510..a65173d61d 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -237,10 +237,16 @@ object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl,
if (cl == itf)
return idx;
- itf2class_T *i2c;
- for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
- if (i2c->i2c_class == cl && i2c->i2c_is_method == is_method)
- break;
+ itf2class_T *i2c = NULL;
+ int searching = TRUE;
+ for (class_T *super = cl; super != NULL && searching;
+ super = super->class_extends)
+ for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
+ if (i2c->i2c_class == super && i2c->i2c_is_method == is_method)
+ {
+ searching = FALSE;
+ break;
+ }
if (i2c == NULL)
{
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)
inside_class(cctx_T *cctx_arg, class_T *cl)
{
for (cctx_T *cctx = cctx_arg; cctx != NULL; cctx = cctx->ctx_outer)
- if (cctx->ctx_ufunc != NULL && cctx->ctx_ufunc->uf_class == cl)
+ if (cctx->ctx_ufunc != NULL
+ && class_instance_of(cctx->ctx_ufunc->uf_class, cl))
return TRUE;
return FALSE;
}