MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / flatten_trait_into_class

Function flatten_trait_into_class

internal/cbm/lsp/php_lsp.c:3451–3506  ·  view source on GitHub ↗

Flatten the methods of a trait into the using class's method table. * * Tree-sitter-php emits `use Trait1, Trait2;` inside a class body as a * `use_declaration` (distinct from the namespace-level * namespace_use_declaration). The optional conflict resolution block * uses `use_instead_of_clause` (for `Trait1::foo insteadof Trait2`) and * `use_as_clause` (for `Trait2::foo as fooAlt`). * * Ph

Source from the content-addressed store, hash-verified

3449 * - skip insteadof (rare in practice; full support deferred)
3450 */
3451static void flatten_trait_into_class(PHPLSPContext *ctx, CBMTypeRegistry *reg, const char *class_qn,
3452 const char *trait_qn, const char *alias_for_method,
3453 const char *only_method_name) {
3454 if (!class_qn || !trait_qn)
3455 return;
3456 /* Resolve trait through alias-style lookup if needed. */
3457 const CBMRegisteredType *t = cbm_registry_lookup_type(reg, trait_qn);
3458 if (!t)
3459 t = lookup_type_with_project(ctx, trait_qn);
3460 const char *canonical_trait_qn = t ? t->qualified_name : trait_qn;
3461
3462 /* Iterate registry funcs whose receiver_type is the trait.
3463 *
3464 * Self-substitution: when the trait's method has a return type that
3465 * names the trait itself (e.g. `tap(): self` registered as
3466 * NAMED(trait_qn)), rewrite it to NAMED(using_class_qn) so chains
3467 * like `$c->tap()->classMethod()` resolve correctly. */
3468 for (int i = 0; i < reg->func_count; i++) {
3469 const CBMRegisteredFunc *src = &reg->funcs[i];
3470 if (!src->receiver_type || strcmp(src->receiver_type, canonical_trait_qn) != 0) {
3471 continue;
3472 }
3473 if (only_method_name && src->short_name && strcmp(src->short_name, only_method_name) != 0) {
3474 continue;
3475 }
3476 const char *new_short = alias_for_method ? alias_for_method : src->short_name;
3477 if (!new_short)
3478 continue;
3479 CBMRegisteredFunc rf;
3480 memset(&rf, 0, sizeof(rf));
3481 rf.qualified_name = cbm_arena_sprintf(ctx->arena, "%s.%s", class_qn, new_short);
3482 rf.short_name = cbm_arena_strdup(ctx->arena, new_short);
3483 rf.receiver_type = class_qn;
3484 rf.min_params = src->min_params;
3485
3486 /* Self-substitute the return type: any NAMED(trait_qn) in the
3487 * signature's return becomes NAMED(class_qn). */
3488 const CBMType *new_sig = src->signature;
3489 if (src->signature && src->signature->kind == CBM_TYPE_FUNC &&
3490 src->signature->data.func.return_types) {
3491 const CBMType *ret0 = src->signature->data.func.return_types[0];
3492 if (ret0 && ret0->kind == CBM_TYPE_NAMED && ret0->data.named.qualified_name &&
3493 strcmp(ret0->data.named.qualified_name, canonical_trait_qn) == 0) {
3494 const CBMType **rets =
3495 (const CBMType **)cbm_arena_alloc(ctx->arena, 2 * sizeof(*rets));
3496 if (rets) {
3497 rets[0] = cbm_type_named(ctx->arena, class_qn);
3498 rets[1] = NULL;
3499 new_sig = cbm_type_func(ctx->arena, NULL, NULL, rets);
3500 }
3501 }
3502 }
3503 rf.signature = new_sig;
3504 cbm_registry_add_func(reg, rf);
3505 }
3506}
3507
3508static void process_trait_use(PHPLSPContext *ctx, CBMTypeRegistry *reg, const char *class_qn,

Callers 1

process_trait_useFunction · 0.85

Calls 8

cbm_registry_lookup_typeFunction · 0.85
lookup_type_with_projectFunction · 0.85
cbm_type_namedFunction · 0.85
cbm_type_funcFunction · 0.85
cbm_registry_add_funcFunction · 0.85
cbm_arena_sprintfFunction · 0.50
cbm_arena_strdupFunction · 0.50
cbm_arena_allocFunction · 0.50

Tested by

no test coverage detected