mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.0.1184: interface of an object is not recognized when checking type
Problem: Interface of an object is not recognized when checking type. Solution: Use the interface implemented by an object.
This commit is contained in:
@@ -1500,6 +1500,7 @@ struct class_S
|
|||||||
// interfaces declared for the class
|
// interfaces declared for the class
|
||||||
int class_interface_count;
|
int class_interface_count;
|
||||||
char_u **class_interfaces; // allocated array of names
|
char_u **class_interfaces; // allocated array of names
|
||||||
|
class_T **class_interfaces_cl; // interfaces (counts as reference)
|
||||||
|
|
||||||
// class members: "static varname"
|
// class members: "static varname"
|
||||||
int class_class_member_count;
|
int class_class_member_count;
|
||||||
|
@@ -455,6 +455,24 @@ def Test_object_type()
|
|||||||
var o: One = Two.new()
|
var o: One = Two.new()
|
||||||
END
|
END
|
||||||
v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
|
v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
interface One
|
||||||
|
def GetMember(): number
|
||||||
|
endinterface
|
||||||
|
class Two implements One
|
||||||
|
this.one = 1
|
||||||
|
def GetMember(): number
|
||||||
|
return this.one
|
||||||
|
enddef
|
||||||
|
endclass
|
||||||
|
|
||||||
|
var o: One = Two.new(5)
|
||||||
|
assert_equal(5, o.GetMember())
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_class_member()
|
def Test_class_member()
|
||||||
|
@@ -695,6 +695,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 */
|
||||||
|
/**/
|
||||||
|
1184,
|
||||||
/**/
|
/**/
|
||||||
1183,
|
1183,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -582,9 +582,13 @@ early_ret:
|
|||||||
}
|
}
|
||||||
VIM_CLEAR(extends);
|
VIM_CLEAR(extends);
|
||||||
|
|
||||||
|
class_T **intf_classes = NULL;
|
||||||
|
|
||||||
// Check all "implements" entries are valid.
|
// Check all "implements" entries are valid.
|
||||||
if (success && ga_impl.ga_len > 0)
|
if (success && ga_impl.ga_len > 0)
|
||||||
{
|
{
|
||||||
|
intf_classes = ALLOC_CLEAR_MULT(class_T *, ga_impl.ga_len);
|
||||||
|
|
||||||
for (int i = 0; i < ga_impl.ga_len && success; ++i)
|
for (int i = 0; i < ga_impl.ga_len && success; ++i)
|
||||||
{
|
{
|
||||||
char_u *impl = ((char_u **)ga_impl.ga_data)[i];
|
char_u *impl = ((char_u **)ga_impl.ga_data)[i];
|
||||||
@@ -605,8 +609,11 @@ early_ret:
|
|||||||
success = FALSE;
|
success = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the members of the interface match the members of the class
|
|
||||||
class_T *ifcl = tv.vval.v_class;
|
class_T *ifcl = tv.vval.v_class;
|
||||||
|
intf_classes[i] = ifcl;
|
||||||
|
++ifcl->class_refcount;
|
||||||
|
|
||||||
|
// check the members of the interface match the members of the class
|
||||||
for (int loop = 1; loop <= 2 && success; ++loop)
|
for (int loop = 1; loop <= 2 && success; ++loop)
|
||||||
{
|
{
|
||||||
// loop == 1: check class members
|
// loop == 1: check class members
|
||||||
@@ -717,6 +724,9 @@ early_ret:
|
|||||||
cl->class_interfaces[i] = ((char_u **)ga_impl.ga_data)[i];
|
cl->class_interfaces[i] = ((char_u **)ga_impl.ga_data)[i];
|
||||||
VIM_CLEAR(ga_impl.ga_data);
|
VIM_CLEAR(ga_impl.ga_data);
|
||||||
ga_impl.ga_len = 0;
|
ga_impl.ga_len = 0;
|
||||||
|
|
||||||
|
cl->class_interfaces_cl = intf_classes;
|
||||||
|
intf_classes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add class and object members to "cl".
|
// Add class and object members to "cl".
|
||||||
@@ -930,6 +940,18 @@ cleanup:
|
|||||||
{
|
{
|
||||||
vim_free(cl->class_name);
|
vim_free(cl->class_name);
|
||||||
vim_free(cl->class_class_functions);
|
vim_free(cl->class_class_functions);
|
||||||
|
if (cl->class_interfaces != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cl->class_interface_count; ++i)
|
||||||
|
vim_free(cl->class_interfaces[i]);
|
||||||
|
vim_free(cl->class_interfaces);
|
||||||
|
}
|
||||||
|
if (cl->class_interfaces_cl != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cl->class_interface_count; ++i)
|
||||||
|
class_unref(cl->class_interfaces_cl[i]);
|
||||||
|
vim_free(cl->class_interfaces_cl);
|
||||||
|
}
|
||||||
vim_free(cl->class_obj_members);
|
vim_free(cl->class_obj_members);
|
||||||
vim_free(cl->class_obj_methods);
|
vim_free(cl->class_obj_methods);
|
||||||
vim_free(cl);
|
vim_free(cl);
|
||||||
@@ -937,6 +959,13 @@ cleanup:
|
|||||||
|
|
||||||
vim_free(extends);
|
vim_free(extends);
|
||||||
class_unref(extends_cl);
|
class_unref(extends_cl);
|
||||||
|
|
||||||
|
if (intf_classes != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ga_impl.ga_len; ++i)
|
||||||
|
class_unref(intf_classes[i]);
|
||||||
|
vim_free(intf_classes);
|
||||||
|
}
|
||||||
ga_clear_strings(&ga_impl);
|
ga_clear_strings(&ga_impl);
|
||||||
|
|
||||||
for (int round = 1; round <= 2; ++round)
|
for (int round = 1; round <= 2; ++round)
|
||||||
@@ -1321,8 +1350,13 @@ class_unref(class_T *cl)
|
|||||||
class_unref(cl->class_extends);
|
class_unref(cl->class_extends);
|
||||||
|
|
||||||
for (int i = 0; i < cl->class_interface_count; ++i)
|
for (int i = 0; i < cl->class_interface_count; ++i)
|
||||||
|
{
|
||||||
vim_free(((char_u **)cl->class_interfaces)[i]);
|
vim_free(((char_u **)cl->class_interfaces)[i]);
|
||||||
|
if (cl->class_interfaces_cl[i] != NULL)
|
||||||
|
class_unref(cl->class_interfaces_cl[i]);
|
||||||
|
}
|
||||||
vim_free(cl->class_interfaces);
|
vim_free(cl->class_interfaces);
|
||||||
|
vim_free(cl->class_interfaces_cl);
|
||||||
|
|
||||||
for (int i = 0; i < cl->class_class_member_count; ++i)
|
for (int i = 0; i < cl->class_class_member_count; ++i)
|
||||||
{
|
{
|
||||||
|
@@ -876,11 +876,21 @@ check_type_maybe(
|
|||||||
}
|
}
|
||||||
else if (expected->tt_type == VAR_OBJECT)
|
else if (expected->tt_type == VAR_OBJECT)
|
||||||
{
|
{
|
||||||
|
// check the class, base class or an implemented interface matches
|
||||||
class_T *cl;
|
class_T *cl;
|
||||||
for (cl = (class_T *)actual->tt_member; cl != NULL;
|
for (cl = (class_T *)actual->tt_member; cl != NULL;
|
||||||
cl = cl->class_extends)
|
cl = cl->class_extends)
|
||||||
|
{
|
||||||
if ((class_T *)expected->tt_member == cl)
|
if ((class_T *)expected->tt_member == cl)
|
||||||
break;
|
break;
|
||||||
|
int i;
|
||||||
|
for (i = cl->class_interface_count - 1; i >= 0; --i)
|
||||||
|
if ((class_T *)expected->tt_member
|
||||||
|
== cl->class_interfaces_cl[i])
|
||||||
|
break;
|
||||||
|
if (i >= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (cl == NULL)
|
if (cl == NULL)
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user