mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-27 06:53:11 +08:00
fix(c-lsp): tag a derived override of an inherited method as lsp_virtual_dispatch
A virtual method called on a concrete derived object (Derived d; d.speak(2), where Derived overrides Base::speak) resolved directly to Derived.speak and was emitted as lsp_type_dispatch. The existing virtual-dispatch path only fired when a method was resolved THROUGH a base with a derived override; an override resolved directly on the derived type was missed. Extend the same notion (a derived override of an inherited method = polymorphic dispatch) to the direct-resolution case: when a method is found directly on the receiver type AND a base class also declares it, emit lsp_virtual_dispatch. This mirrors the codebase's existing heuristic definition of virtual dispatch (an override exists) rather than the textual 'virtual' keyword, so it stays consistent. lsp_type_dispatch and lsp_base_dispatch fixtures are unaffected. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
@@ -2567,6 +2567,26 @@ const CBMRegisteredFunc *c_lookup_member(CLSPContext *ctx, const char *type_qn,
|
||||
return c_lookup_member_depth(ctx, type_qn, member_name, 0);
|
||||
}
|
||||
|
||||
// True if any BASE class of type_qn (not type_qn itself) declares member_name —
|
||||
// i.e. a method found directly on type_qn is an OVERRIDE of an inherited method.
|
||||
// This mirrors the existing virtual-dispatch notion (a derived override of a base
|
||||
// method) for the case where the override is resolved directly on the derived
|
||||
// type rather than through the base.
|
||||
static bool c_base_declares_member(CLSPContext *ctx, const char *type_qn, const char *member_name) {
|
||||
const CBMRegisteredType *rt = cbm_registry_lookup_type(ctx->registry, type_qn);
|
||||
if (!rt && ctx->module_qn) {
|
||||
rt = cbm_registry_lookup_type(
|
||||
ctx->registry, cbm_arena_sprintf(ctx->arena, "%s.%s", ctx->module_qn, type_qn));
|
||||
}
|
||||
if (!rt || !rt->embedded_types)
|
||||
return false;
|
||||
for (int i = 0; rt->embedded_types[i]; i++) {
|
||||
if (c_lookup_member(ctx, rt->embedded_types[i], member_name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Field type lookup
|
||||
static const CBMType *c_lookup_field_type(CLSPContext *ctx, const char *type_qn,
|
||||
const char *field_name, int depth) {
|
||||
@@ -3413,6 +3433,11 @@ static void c_resolve_calls_in_node_inner(CLSPContext *ctx, TSNode node) {
|
||||
} else {
|
||||
strategy = "lsp_base_dispatch";
|
||||
}
|
||||
} else if (c_base_declares_member(ctx, type_qn, field_name)) {
|
||||
// Method resolved directly on type_qn but also
|
||||
// declared in a base → a derived override of an
|
||||
// inherited (virtual) method → polymorphic dispatch.
|
||||
strategy = "lsp_virtual_dispatch";
|
||||
}
|
||||
// Check if through smart pointer
|
||||
if (is_arrow && obj_type->kind == CBM_TYPE_TEMPLATE &&
|
||||
|
||||
Reference in New Issue
Block a user