MCPcopy
hub / github.com/colbymchenry/codegraph / objectRegistryEdges

Function objectRegistryEdges

src/resolution/callback-synthesizer.ts:1807–1884  ·  view source on GitHub ↗
(ctx: ResolutionContext, onYield: MaybeYield)

Source from the content-addressed store, hash-verified

1805}
1806
1807async function objectRegistryEdges(ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]> {
1808 const edges: Edge[] = [];
1809 const seen = new Set<string>();
1810 let scanned = 0;
1811 for (const file of ctx.getAllFiles()) {
1812 if ((++scanned & 255) === 0) await onYield(); // #1091: yield mid-scan on huge graphs
1813 if (!REGISTRY_JS_EXT.test(file)) continue;
1814 const content = ctx.readFile(file);
1815 // Cheap pre-filter: a computed member access BY NAME (`ident[ident`) — the dispatch shape.
1816 if (!content || !/[\w$]\s*\[\s*[A-Za-z_$]/.test(content)) continue;
1817 // Skip minified/generated bundles (draco, three.min, base64…): their pervasive `h[x](...)`
1818 // calls + single-letter `{a:b}` literals are a false-positive minefield. Average line
1819 // length is the reliable tell — real source ~30–80, minified in the hundreds/thousands.
1820 const newlines = (content.match(/\n/g)?.length ?? 0) + 1;
1821 if (content.length / newlines > 200) continue;
1822 const safe = stripCommentsForRegex(content, /\.(?:jsx?|mjs|cjs)$/.test(file) ? 'javascript' : 'typescript');
1823
1824 // 1. Dispatch sites: `(new )?<ref>[<ident-key>]` followed by a call or a chained method.
1825 // A quoted-string key (`['save']`) does NOT match — that's a static access, not dispatch.
1826 REGISTRY_DISPATCH_RE.lastIndex = 0;
1827 const dispatches: Array<{ ref: string; line: number; chained: string | null }> = [];
1828 let dm: RegExpExecArray | null;
1829 while ((dm = REGISTRY_DISPATCH_RE.exec(safe))) {
1830 const win = safe.slice(dm.index, dm.index + 160);
1831 const cm = /\]\s*\([^)]*\)\s*\.\s*([A-Za-z_$][\w$]*)/.exec(win) || /\]\s*\.\s*([A-Za-z_$][\w$]*)/.exec(win);
1832 dispatches.push({ ref: dm[1]!, line: safe.slice(0, dm.index).split('\n').length, chained: cm ? cm[1]! : null });
1833 }
1834 if (!dispatches.length) continue;
1835 // Normalize a leading `this.` so a class FIELD-INITIALIZER registry (`commands = {…}`)
1836 // matches a `this.commands[k]` dispatch, not just the constructor form `this.commands = {…}`.
1837 const norm = (r: string) => r.replace(/^this\./, '');
1838 const refs = new Set(dispatches.map((d) => norm(d.ref)));
1839
1840 // 2. Registries: an object literal assigned to a dispatched ref, ≥2 entries resolving to callables.
1841 REGISTRY_ASSIGN_RE.lastIndex = 0;
1842 const registries = new Map<string, { names: string[]; line: number }>();
1843 let am: RegExpExecArray | null;
1844 while ((am = REGISTRY_ASSIGN_RE.exec(safe))) {
1845 const lhs = norm(am[1] ?? am[2]!);
1846 if (!refs.has(lhs) || registries.has(lhs)) continue;
1847 const body = braceBody(safe, am.index + am[0].length - 1);
1848 if (!body) continue;
1849 const names = registryEntryNames(body); // depth-0 `key: Identifier` entries only
1850 if (names.length >= REGISTRY_MIN_ENTRIES) {
1851 registries.set(lhs, { names, line: safe.slice(0, am.index).split('\n').length });
1852 }
1853 }
1854 if (!registries.size) continue;
1855
1856 // 3. Link each dispatcher → each registered handler's callable entry.
1857 const nodesInFile = ctx.getNodesInFile(file);
1858 for (const d of dispatches) {
1859 const reg = registries.get(norm(d.ref));
1860 if (!reg) continue;
1861 const disp = enclosingFn(nodesInFile, d.line);
1862 if (!disp) continue;
1863 let added = 0;
1864 for (const name of reg.names) {

Callers 1

synthesizeCallbackEdgesFunction · 0.85

Calls 13

stripCommentsForRegexFunction · 0.90
braceBodyFunction · 0.85
registryEntryNamesFunction · 0.85
enclosingFnFunction · 0.85
resolveRegistryHandlerFunction · 0.85
readFileMethod · 0.80
hasMethod · 0.80
setMethod · 0.80
normFunction · 0.70
getAllFilesMethod · 0.65
execMethod · 0.65
getNodesInFileMethod · 0.65

Tested by

no test coverage detected