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

Function resolve_function_call

internal/cbm/lsp/php_lsp.c:1594–1678  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1592/* ── call resolution ────────────────────────────────────────────── */
1593
1594static void resolve_function_call(PHPLSPContext *ctx, TSNode call, CBMResolvedKind kind) {
1595 TSNode fn = ts_node_child_by_field_name(call, "function", 8);
1596 if (ts_node_is_null(fn))
1597 return;
1598 char *name = php_node_text(ctx, fn);
1599 if (!name)
1600 return;
1601
1602 /* In PHP, `$handler(...)` is syntactically a function-call expression but
1603 * a typed object value dispatches to its materialized `__invoke` method.
1604 * This is precise only for a first-class callable and a receiver type whose
1605 * exact method exists in the registry; otherwise leave it unresolved so
1606 * the usage pipeline can retain ordinary value semantics. */
1607 if (kind == CBM_RESOLVED_CALL_REFERENCE && strcmp(ts_node_type(fn), "variable_name") == 0) {
1608 const CBMType *receiver = php_eval_expr_type(ctx, fn);
1609 const char *class_qn = NULL;
1610 if (receiver && receiver->kind == CBM_TYPE_NAMED) {
1611 class_qn = receiver->data.named.qualified_name;
1612 } else if (receiver && receiver->kind == CBM_TYPE_TEMPLATE) {
1613 class_qn = receiver->data.template_type.template_name;
1614 }
1615 const CBMRegisteredFunc *invoke =
1616 class_qn ? php_lookup_method(ctx, class_qn, "__invoke") : NULL;
1617 if (invoke && invoke->qualified_name) {
1618 emit_resolved_reason_kind(ctx, invoke->qualified_name, "php_invokable_reference", 0.95f,
1619 name, kind);
1620 }
1621 return;
1622 }
1623
1624 /* `use function Foo\\bar;` mapping. */
1625 const char *target = find_use(ctx, name, CBM_PHP_USE_FUNCTION);
1626 if (target) {
1627 const CBMRegisteredFunc *f = cbm_registry_lookup_func(ctx->registry, target);
1628 if (f) {
1629 emit_resolved_kind(ctx, f->qualified_name, "php_function_namespaced", 0.95f, kind);
1630 return;
1631 }
1632 }
1633
1634 /* Current namespace, then global fallback. */
1635 if (ctx->current_namespace_qn && ctx->current_namespace_qn[0]) {
1636 const char *ns_qn = cbm_arena_sprintf(ctx->arena, "%s.%s", ctx->current_namespace_qn, name);
1637 const CBMRegisteredFunc *f = cbm_registry_lookup_func(ctx->registry, ns_qn);
1638 if (f) {
1639 emit_resolved_kind(ctx, f->qualified_name, "php_function_namespaced", 0.95f, kind);
1640 return;
1641 }
1642 }
1643
1644 /* Look for any free function with this short_name. Prefer the one in the
1645 * file's project (i.e. with the longest module-prefix overlap). */
1646 const CBMRegisteredFunc *best = NULL;
1647 int best_score = -1;
1648 for (int i = 0; ctx->registry && i < ctx->registry->func_count; i++) {
1649 const CBMRegisteredFunc *cand = &ctx->registry->funcs[i];
1650 if (cand->receiver_type)
1651 continue;

Callers 1

Calls 8

php_node_textFunction · 0.85
php_eval_expr_typeFunction · 0.85
php_lookup_methodFunction · 0.85
find_useFunction · 0.85
cbm_registry_lookup_funcFunction · 0.85
emit_resolved_kindFunction · 0.85
cbm_arena_sprintfFunction · 0.50

Tested by

no test coverage detected