mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-27 06:53:11 +08:00
Merge pull request #1011 from DeusData/fix/import-map-suffix-swallow
fix(registry): don't swallow call suffixes on aliased-import direct hits
This commit is contained in:
+13
-3
@@ -618,9 +618,19 @@ static cbm_resolution_t resolve_import_map(const cbm_registry_t *r, const char *
|
||||
* function name and suffix is NULL, so the target QN must be
|
||||
* resolved.requireAdmin — not just resolved, which would point at the
|
||||
* module node and miss the function entirely. */
|
||||
const char *direct = cbm_ht_get_key(r->exact, resolved);
|
||||
if (direct) {
|
||||
return (cbm_resolution_t){direct, "import_map", CONF_IMPORT_MAP, REG_RESOLVED};
|
||||
/* Direct hit ONLY for suffix-less callees (an aliased direct-symbol
|
||||
* import called bare: `from m import f as g; g()` — #875/#979). With a
|
||||
* suffix present (`imported.method()`), returning the bare base here
|
||||
* would swallow the suffix and bind the call to the imported symbol's
|
||||
* own node (a Variable/Class/module) instead of base.method — exactly
|
||||
* the mis-resolution the comment above warns about. That regressed
|
||||
* django-scale graphs by ~11K CALLS/TESTS edges (Signal.send calls
|
||||
* degraded to edges onto the signal variables themselves). #1000 */
|
||||
if (!suffix || !suffix[0]) {
|
||||
const char *direct = cbm_ht_get_key(r->exact, resolved);
|
||||
if (direct) {
|
||||
return (cbm_resolution_t){direct, "import_map", CONF_IMPORT_MAP, REG_RESOLVED};
|
||||
}
|
||||
}
|
||||
char candidate[CBM_SZ_512];
|
||||
if (suffix && suffix[0]) {
|
||||
|
||||
@@ -805,6 +805,28 @@ TEST(tsjs_suppress_keeps_high_confidence_and_non_methods) {
|
||||
|
||||
/* ── Suite ─────────────────────────────────────────────────────── */
|
||||
|
||||
/* Method call THROUGH an imported symbol that is itself an indexed node
|
||||
* (`from m import sig; sig.send()`). The import-map value is the symbol QN
|
||||
* and the callee carries a suffix — resolution must return symbol.send, NOT
|
||||
* the bare symbol node. The #979 direct-hit early return swallowed the
|
||||
* suffix whenever the base symbol existed as an exact node, degrading
|
||||
* django-scale graphs by ~11K CALLS/TESTS edges (e.g. every
|
||||
* `user_logged_in.send(...)` bound to the signal VARIABLE instead of
|
||||
* Signal.send). Regression guard for #1000. */
|
||||
TEST(resolve_import_map_alias_with_suffix_hits_method) {
|
||||
cbm_registry_t *r = cbm_registry_new();
|
||||
cbm_registry_add(r, "user_logged_in", "proj.auth.signals.user_logged_in", "Variable");
|
||||
cbm_registry_add(r, "send", "proj.auth.signals.user_logged_in.send", "Method");
|
||||
const char *keys[] = {"user_logged_in"};
|
||||
const char *vals[] = {"proj.auth.signals.user_logged_in"};
|
||||
cbm_resolution_t res =
|
||||
cbm_registry_resolve(r, "user_logged_in.send", "proj.auth.views", keys, vals, 1);
|
||||
ASSERT_STR_EQ(res.qualified_name, "proj.auth.signals.user_logged_in.send");
|
||||
ASSERT_STR_EQ(res.strategy, "import_map");
|
||||
cbm_registry_free(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
SUITE(registry) {
|
||||
/* FQN */
|
||||
RUN_TEST(fqn_simple);
|
||||
@@ -838,6 +860,7 @@ SUITE(registry) {
|
||||
RUN_TEST(resolve_import_map);
|
||||
RUN_TEST(resolve_import_map_bare_function);
|
||||
RUN_TEST(resolve_import_map_bare_alias);
|
||||
RUN_TEST(resolve_import_map_alias_with_suffix_hits_method);
|
||||
RUN_TEST(resolve_unique_name);
|
||||
RUN_TEST(resolve_unresolved);
|
||||
RUN_TEST(resolve_many_nodes);
|
||||
|
||||
Reference in New Issue
Block a user