* The anchor: `anchor= `, or `symbol= ` resolved to the most * screen-like symbol of that name — a route first, then a component or * function, then a method — with the rest reported as `ambiguous`.
(cg: CodeGraph, query: URLSearchParams)
| 1496 | * function, then a method — with the rest reported as `ambiguous`. |
| 1497 | */ |
| 1498 | function resolveAnchor(cg: CodeGraph, query: URLSearchParams): { anchor: Node; ambiguous: WireNodeRef[] } { |
| 1499 | const id = query.get('anchor'); |
| 1500 | if (id !== null && id.trim() !== '') { |
| 1501 | const node = cg.getNode(id); |
| 1502 | if (!node) throw notFound(`No symbol with id "${id}" in this index.`, 'It may have moved in a re-index; open it from search or the Screens view.'); |
| 1503 | return { anchor: node, ambiguous: [] }; |
| 1504 | } |
| 1505 | const name = query.get('symbol'); |
| 1506 | if (name === null || name.trim() === '') throw badRequest('Give the picture an anchor: ?anchor=<node id> or ?symbol=<name>.'); |
| 1507 | const rank: Record<string, number> = { route: 0, component: 1, function: 2, method: 3, class: 4, constant: 5, variable: 6 }; |
| 1508 | const matches = cg |
| 1509 | .getNodesByName(name.trim()) |
| 1510 | .filter((n) => n.kind !== 'file' && n.kind !== 'import' && n.kind !== 'export') |
| 1511 | .sort((a, b) => (rank[a.kind] ?? 9) - (rank[b.kind] ?? 9) || a.filePath.localeCompare(b.filePath) || a.startLine - b.startLine); |
| 1512 | const anchor = matches[0]; |
| 1513 | if (!anchor) throw notFound(`Nothing in this index is named "${name}".`, 'Try the search box; names are matched exactly.'); |
| 1514 | return { anchor, ambiguous: matches.slice(1, 9).map(toNodeRef) }; |
| 1515 | } |
| 1516 | |
| 1517 | /** How many distinct parents render this node as a JSX child. Memoised per request. */ |
| 1518 | function renderParents(cg: CodeGraph, node: Node, memo: Map<string, number>): number { |
no test coverage detected