Mercurial > vim
comparison src/vim9class.c @ 33211:71a097aab64d v9.0.1883
patch 9.0.1883: Vim9: Calling an interface method using a child object fails
Commit: https://github.com/vim/vim/commit/cc0bcf4c9f4133750f5ee99c685ba995a1b840fd
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Fri Sep 8 19:12:03 2023 +0200
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>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 08 Sep 2023 19:15:08 +0200 |
parents | 36aebbf8389f |
children | 499ba27ba0f6 |
comparison
equal
deleted
inserted
replaced
33210:039954b5721d | 33211:71a097aab64d |
---|---|
235 // index can be used directly and there is no need to search for the method | 235 // index can be used directly and there is no need to search for the method |
236 // index in one of the child classes. | 236 // index in one of the child classes. |
237 if (cl == itf) | 237 if (cl == itf) |
238 return idx; | 238 return idx; |
239 | 239 |
240 itf2class_T *i2c = NULL; | 240 itf2class_T *i2c = NULL; |
241 int searching = TRUE; | 241 int searching = TRUE; |
242 int method_offset = 0; | |
243 | |
242 for (class_T *super = cl; super != NULL && searching; | 244 for (class_T *super = cl; super != NULL && searching; |
243 super = super->class_extends) | 245 super = super->class_extends) |
246 { | |
244 for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next) | 247 for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next) |
248 { | |
245 if (i2c->i2c_class == super && i2c->i2c_is_method == is_method) | 249 if (i2c->i2c_class == super && i2c->i2c_is_method == is_method) |
246 { | 250 { |
247 searching = FALSE; | 251 searching = FALSE; |
248 break; | 252 break; |
249 } | 253 } |
254 } | |
255 if (searching && is_method) | |
256 // The parent class methods are stored after the current class | |
257 // methods. | |
258 method_offset += is_static | |
259 ? super->class_class_function_count_child | |
260 : super->class_obj_method_count_child; | |
261 } | |
250 if (i2c == NULL) | 262 if (i2c == NULL) |
251 { | 263 { |
252 siemsg("class %s not found on interface %s", | 264 siemsg("class %s not found on interface %s", |
253 cl->class_name, itf->class_name); | 265 cl->class_name, itf->class_name); |
254 return 0; | 266 return 0; |
271 } | 283 } |
272 else | 284 else |
273 { | 285 { |
274 // A table follows the i2c for the class | 286 // A table follows the i2c for the class |
275 int *table = (int *)(i2c + 1); | 287 int *table = (int *)(i2c + 1); |
276 return table[idx]; | 288 // "method_offset" is 0, if method is in the current class. If method |
289 // is in a parent class, then it is non-zero. | |
290 return table[idx] + method_offset; | |
277 } | 291 } |
278 } | 292 } |
279 | 293 |
280 /* | 294 /* |
281 * Check whether a class named "extends_name" is present. If the class is | 295 * Check whether a class named "extends_name" is present. If the class is |