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

Function ginMiddlewareChainEdges

src/resolution/callback-synthesizer.ts:1524–1582  ·  view source on GitHub ↗
(queries: QueryBuilder, ctx: ResolutionContext)

Source from the content-addressed store, hash-verified

1522}
1523
1524function ginMiddlewareChainEdges(queries: QueryBuilder, ctx: ResolutionContext): Edge[] {
1525 // 1. Find the chain dispatcher(s): a Go method that invokes a `handlers` slice by index.
1526 const dispatchers: Node[] = [];
1527 for (const n of queries.iterateNodesByKind('method')) {
1528 if (n.language !== 'go') continue;
1529 const content = ctx.readFile(n.filePath);
1530 const src = content && sliceLines(content, n.startLine, n.endLine);
1531 if (src && GIN_DISPATCH_RE.test(src)) dispatchers.push(n);
1532 }
1533 if (dispatchers.length === 0) return []; // not a gin repo — bail
1534
1535 // 2. Collect handler identifiers registered via gin registration calls
1536 // (.Use / .GET / … / .Handle). String args (paths/methods) and inline
1537 // closures are dropped by goHandlerIdent; the rest are HandlerFuncs.
1538 const registered = new Map<string, string>(); // name → registeredAt (file:line)
1539 for (const file of ctx.getAllFiles()) {
1540 if (!file.endsWith('.go')) continue;
1541 const content = ctx.readFile(file);
1542 if (!content || (!content.includes('.Use(') && !/\.(?:GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD|Any|Handle)\(/.test(content))) continue;
1543 const safe = stripCommentsForRegex(content, 'go');
1544 GIN_REG_RE.lastIndex = 0;
1545 let m: RegExpExecArray | null;
1546 while ((m = GIN_REG_RE.exec(safe))) {
1547 const parenIdx = m.index + m[0].length - 1;
1548 const argStr = goBalancedArgs(safe, parenIdx);
1549 if (!argStr) continue;
1550 const line = safe.slice(0, m.index).split('\n').length;
1551 for (const arg of goSplitArgs(argStr)) {
1552 const name = goHandlerIdent(arg);
1553 if (name && !registered.has(name)) registered.set(name, `${file}:${line}`);
1554 }
1555 }
1556 }
1557 if (registered.size === 0) return [];
1558
1559 // 3. Link each dispatcher → each registered handler node (dedup, capped).
1560 const edges: Edge[] = [];
1561 const seen = new Set<string>();
1562 for (const disp of dispatchers) {
1563 let added = 0;
1564 for (const [name, registeredAt] of registered) {
1565 if (added >= MAX_CALLBACKS_PER_CHANNEL) break;
1566 const handler = ctx.getNodesByName(name).find(
1567 (n) => (n.kind === 'function' || n.kind === 'method') && n.language === 'go'
1568 );
1569 if (!handler || handler.id === disp.id) continue;
1570 const key = `${disp.id}>${handler.id}`;
1571 if (seen.has(key)) continue;
1572 seen.add(key);
1573 edges.push({
1574 source: disp.id, target: handler.id, kind: 'calls', line: disp.startLine,
1575 provenance: 'heuristic',
1576 metadata: { synthesizedBy: 'gin-middleware-chain', via: name, registeredAt },
1577 });
1578 added++;
1579 }
1580 }
1581 return edges;

Callers 1

synthesizeCallbackEdgesFunction · 0.85

Calls 12

stripCommentsForRegexFunction · 0.90
goBalancedArgsFunction · 0.85
goSplitArgsFunction · 0.85
goHandlerIdentFunction · 0.85
iterateNodesByKindMethod · 0.80
readFileMethod · 0.80
hasMethod · 0.80
setMethod · 0.80
sliceLinesFunction · 0.70
getAllFilesMethod · 0.65
execMethod · 0.65
getNodesByNameMethod · 0.65

Tested by

no test coverage detected