What
For a qualified call ns.f(), the resolver's import shortcut matches the qualifier against the stems and directory names of the files the caller imports (imported_stems / imported_dirs in call_resolver._resolve_one). A namespace import binds an alias, and the alias is often not the file's name:
import * as processors from "./json-schema-processors.js";
processors.dateProcessor(inst, ctx, json, params);
The stem is json-schema-processors, not processors, so the shortcut misses. The call falls to the untyped-receiver ladder, which only reaches methods, and dateProcessor is a free function, so it resolves to nothing.
Evidence
callgraph_triage.py typescript (#3774) on zod: 53 reference edges in the resolved_outside bucket are processors.x() calls. These are counts from triage, not yet checked against the source.
Likely fix
This needs the alias → module mapping for namespace imports (import * as ns from "…", and const ns = require("…") in JS). Two ways to get it:
- the import-graph edge could carry the local alias (
entity_imports already exists on edge_data);
- the detector could record namespace aliases per file.
Then ns.f() resolves through the import step to the file the alias names. The same mechanism would also serve #3758's remaining named-import case.
What
For a qualified call
ns.f(), the resolver's import shortcut matches the qualifier against the stems and directory names of the files the caller imports (imported_stems/imported_dirsincall_resolver._resolve_one). A namespace import binds an alias, and the alias is often not the file's name:The stem is
json-schema-processors, notprocessors, so the shortcut misses. The call falls to the untyped-receiver ladder, which only reaches methods, anddateProcessoris a free function, so it resolves to nothing.Evidence
callgraph_triage.py typescript(#3774) on zod: 53 reference edges in theresolved_outsidebucket areprocessors.x()calls. These are counts from triage, not yet checked against the source.Likely fix
This needs the alias → module mapping for namespace imports (
import * as ns from "…", andconst ns = require("…")in JS). Two ways to get it:entity_importsalready exists onedge_data);Then
ns.f()resolves through theimportstep to the file the alias names. The same mechanism would also serve #3758's remaining named-import case.