mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 9.0.1883: Vim9: Calling an interface method using a child object fails
Problem: Vim9: Calling an interface method using a child object fails Solution: Search methods of parent class When a class implementing an interface is extended by another class and a child class instance is passed to a function that accepts the interface, calling an interface method doesn't work properly. closes: #13053 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
parent
11d2aeeca4
commit
cc0bcf4c9f
@ -4396,4 +4396,81 @@ def Test_class_member_access_using_object()
|
|||||||
v9.CheckScriptSuccess(lines)
|
v9.CheckScriptSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
" Test for using a interface method using a child object
|
||||||
|
def Test_interface_method_from_child()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
interface A
|
||||||
|
def Foo(): string
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
class B implements A
|
||||||
|
def Foo(): string
|
||||||
|
return 'foo'
|
||||||
|
enddef
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class C extends B
|
||||||
|
def Bar(): string
|
||||||
|
return 'bar'
|
||||||
|
enddef
|
||||||
|
endclass
|
||||||
|
|
||||||
|
def T1(a: A)
|
||||||
|
assert_equal('foo', a.Foo())
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def T2(b: B)
|
||||||
|
assert_equal('foo', b.Foo())
|
||||||
|
enddef
|
||||||
|
|
||||||
|
var c = C.new()
|
||||||
|
T1(c)
|
||||||
|
T2(c)
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
" Test for using an interface method using a child object when it is overridden
|
||||||
|
" by the child class.
|
||||||
|
" FIXME: This test fails.
|
||||||
|
" def Test_interface_overridden_method_from_child()
|
||||||
|
" var lines =<< trim END
|
||||||
|
" vim9script
|
||||||
|
"
|
||||||
|
" interface A
|
||||||
|
" def Foo(): string
|
||||||
|
" endinterface
|
||||||
|
"
|
||||||
|
" class B implements A
|
||||||
|
" def Foo(): string
|
||||||
|
" return 'b-foo'
|
||||||
|
" enddef
|
||||||
|
" endclass
|
||||||
|
"
|
||||||
|
" class C extends B
|
||||||
|
" def Bar(): string
|
||||||
|
" return 'bar'
|
||||||
|
" enddef
|
||||||
|
" def Foo(): string
|
||||||
|
" return 'c-foo'
|
||||||
|
" enddef
|
||||||
|
" endclass
|
||||||
|
"
|
||||||
|
" def T1(a: A)
|
||||||
|
" assert_equal('c-foo', a.Foo())
|
||||||
|
" enddef
|
||||||
|
"
|
||||||
|
" def T2(b: B)
|
||||||
|
" assert_equal('c-foo', b.Foo())
|
||||||
|
" enddef
|
||||||
|
"
|
||||||
|
" var c = C.new()
|
||||||
|
" T1(c)
|
||||||
|
" T2(c)
|
||||||
|
" END
|
||||||
|
" v9.CheckScriptSuccess(lines)
|
||||||
|
" enddef
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@ -699,6 +699,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1883,
|
||||||
/**/
|
/**/
|
||||||
1882,
|
1882,
|
||||||
/**/
|
/**/
|
||||||
|
@ -237,16 +237,28 @@ object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl,
|
|||||||
if (cl == itf)
|
if (cl == itf)
|
||||||
return idx;
|
return idx;
|
||||||
|
|
||||||
itf2class_T *i2c = NULL;
|
itf2class_T *i2c = NULL;
|
||||||
int searching = TRUE;
|
int searching = TRUE;
|
||||||
|
int method_offset = 0;
|
||||||
|
|
||||||
for (class_T *super = cl; super != NULL && searching;
|
for (class_T *super = cl; super != NULL && searching;
|
||||||
super = super->class_extends)
|
super = super->class_extends)
|
||||||
|
{
|
||||||
for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
|
for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
|
||||||
|
{
|
||||||
if (i2c->i2c_class == super && i2c->i2c_is_method == is_method)
|
if (i2c->i2c_class == super && i2c->i2c_is_method == is_method)
|
||||||
{
|
{
|
||||||
searching = FALSE;
|
searching = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (searching && is_method)
|
||||||
|
// The parent class methods are stored after the current class
|
||||||
|
// methods.
|
||||||
|
method_offset += is_static
|
||||||
|
? super->class_class_function_count_child
|
||||||
|
: super->class_obj_method_count_child;
|
||||||
|
}
|
||||||
if (i2c == NULL)
|
if (i2c == NULL)
|
||||||
{
|
{
|
||||||
siemsg("class %s not found on interface %s",
|
siemsg("class %s not found on interface %s",
|
||||||
@ -273,7 +285,9 @@ object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl,
|
|||||||
{
|
{
|
||||||
// A table follows the i2c for the class
|
// A table follows the i2c for the class
|
||||||
int *table = (int *)(i2c + 1);
|
int *table = (int *)(i2c + 1);
|
||||||
return table[idx];
|
// "method_offset" is 0, if method is in the current class. If method
|
||||||
|
// is in a parent class, then it is non-zero.
|
||||||
|
return table[idx] + method_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user