(ctx: ResolutionContext, onYield: MaybeYield)
| 1740 | } |
| 1741 | |
| 1742 | async function fabricNativeImplEdges(ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]> { |
| 1743 | let scanned255 = 0; |
| 1744 | const edges: Edge[] = []; |
| 1745 | const seen = new Set<string>(); |
| 1746 | |
| 1747 | // The Fabric extractor IDs are prefixed `fabric-component:` so we can |
| 1748 | // filter to just those while streaming — never materializing the whole |
| 1749 | // `component` kind (#1212). |
| 1750 | const components: Node[] = []; |
| 1751 | for (const n of (ctx.iterateNodesByKind?.('component') ?? ctx.getNodesByKind('component'))) { |
| 1752 | if ((++scanned255 & 63) === 0) await onYield(); |
| 1753 | if (n.id.startsWith('fabric-component:')) components.push(n); |
| 1754 | } |
| 1755 | if (components.length === 0) return edges; |
| 1756 | |
| 1757 | // Pre-index native classes by name for O(1) lookup. |
| 1758 | const nativeClassesByName = new Map<string, Node[]>(); |
| 1759 | for (const n of (ctx.iterateNodesByKind?.('class') ?? ctx.getNodesByKind('class'))) { |
| 1760 | if ((++scanned255 & 63) === 0) await onYield(); |
| 1761 | if (n.language !== 'objc' && n.language !== 'kotlin' && n.language !== 'java' && n.language !== 'cpp') continue; |
| 1762 | const arr = nativeClassesByName.get(n.name); |
| 1763 | if (arr) arr.push(n); |
| 1764 | else nativeClassesByName.set(n.name, [n]); |
| 1765 | } |
| 1766 | |
| 1767 | for (const component of components) { |
| 1768 | for (const suffix of FABRIC_NATIVE_SUFFIXES) { |
| 1769 | const candidate = component.name + suffix; |
| 1770 | const matches = nativeClassesByName.get(candidate); |
| 1771 | if (!matches || matches.length === 0) continue; |
| 1772 | // Link the component node to every matching native class (iOS + |
| 1773 | // Android each have one). |
| 1774 | for (const native of matches) { |
| 1775 | const key = `${component.id}>${native.id}`; |
| 1776 | if (seen.has(key)) continue; |
| 1777 | seen.add(key); |
| 1778 | edges.push({ |
| 1779 | source: component.id, |
| 1780 | target: native.id, |
| 1781 | kind: 'calls', |
| 1782 | provenance: 'heuristic', |
| 1783 | metadata: { |
| 1784 | synthesizedBy: 'fabric-native-impl', |
| 1785 | viaSuffix: suffix || '(exact)', |
| 1786 | componentName: component.name, |
| 1787 | }, |
| 1788 | }); |
| 1789 | } |
| 1790 | } |
| 1791 | } |
| 1792 | |
| 1793 | return edges; |
| 1794 | } |
| 1795 | |
| 1796 | /** |
| 1797 | * MyBatis: link a Java mapper interface method to the XML statement that holds |
no test coverage detected