* Phase 4c: C++ virtual override. A call through a base/interface pointer * (`db->Get(...)`, `iter->Next()`) dispatches at runtime to a subclass override, * but that hop is a vtable indirection — no static call edge — so a flow stops at * the abstract base method. Bridge it like react-render: for
(queries: QueryBuilder)
| 428 | * per class and gated to C++ to avoid touching other languages' dispatch. |
| 429 | */ |
| 430 | function cppOverrideEdges(queries: QueryBuilder): Edge[] { |
| 431 | const edges: Edge[] = []; |
| 432 | const seen = new Set<string>(); |
| 433 | const methodsOf = (classId: string): Node[] => |
| 434 | queries |
| 435 | .getOutgoingEdges(classId, ['contains']) |
| 436 | .map((e) => queries.getNodeById(e.target)) |
| 437 | .filter((n): n is Node => !!n && n.kind === 'method'); |
| 438 | for (const cls of queries.getNodesByKind('class')) { |
| 439 | const subMethods = methodsOf(cls.id).filter((n) => n.language === 'cpp'); |
| 440 | if (subMethods.length === 0) continue; |
| 441 | for (const ext of queries.getOutgoingEdges(cls.id, ['extends'])) { |
| 442 | const base = queries.getNodeById(ext.target); |
| 443 | if (!base || base.language !== 'cpp' || base.id === cls.id) continue; |
| 444 | const baseMethods = new Map(methodsOf(base.id).map((m) => [m.name, m])); |
| 445 | let added = 0; |
| 446 | for (const m of subMethods) { |
| 447 | if (added >= MAX_CALLBACKS_PER_CHANNEL) break; |
| 448 | const bm = baseMethods.get(m.name); |
| 449 | if (!bm || bm.id === m.id) continue; |
| 450 | const key = `${bm.id}>${m.id}`; |
| 451 | if (seen.has(key)) continue; |
| 452 | seen.add(key); |
| 453 | edges.push({ |
| 454 | source: bm.id, |
| 455 | target: m.id, |
| 456 | kind: 'calls', |
| 457 | line: bm.startLine, |
| 458 | provenance: 'heuristic', |
| 459 | metadata: { synthesizedBy: 'cpp-override', via: m.name, registeredAt: `${m.filePath}:${m.startLine}` }, |
| 460 | }); |
| 461 | added++; |
| 462 | } |
| 463 | } |
| 464 | } |
| 465 | return edges; |
| 466 | } |
| 467 | |
| 468 | /** |
| 469 | * Phase 5.5: interface / abstract dispatch (Java, Kotlin). A call through an |
no test coverage detected