* Infer the class produced by a C++ call/construction expression, using return * types captured at extraction (#645). Handles, in order: * - `make_unique ()` / `make_shared ()` → T * - single-level member call `recv.method()` → recv's type, then method's return * - `Class:
( inner: string, ref: UnresolvedRef, context: ResolutionContext, depth = 0, )
| 817 | * exists on the result before creating an edge, so a wrong guess stays silent. |
| 818 | */ |
| 819 | function resolveCppCallResultType( |
| 820 | inner: string, |
| 821 | ref: UnresolvedRef, |
| 822 | context: ResolutionContext, |
| 823 | depth = 0, |
| 824 | ): string | null { |
| 825 | if (depth > 3) return null; // guard against pathological mutual recursion |
| 826 | const expr = inner.trim(); |
| 827 | |
| 828 | const make = expr.match(/(?:^|::)(?:make_unique|make_shared)\s*<\s*([A-Za-z_]\w*)/); |
| 829 | if (make) return make[1] ?? null; |
| 830 | |
| 831 | // Single-level member call `recv.method` (the `manager.view().render()` shape). |
| 832 | const dotIdx = expr.lastIndexOf('.'); |
| 833 | if (dotIdx > 0) { |
| 834 | const recv = expr.slice(0, dotIdx); |
| 835 | const method = expr.slice(dotIdx + 1); |
| 836 | if (recv.includes('.') || recv.includes('(') || recv.includes('::')) return null; // single level only |
| 837 | const recvType = inferCppReceiverType(recv, ref, context, depth + 1); |
| 838 | if (!recvType) return null; |
| 839 | return lookupCalleeReturnType(`${recvType}::${method}`, ref, context); |
| 840 | } |
| 841 | |
| 842 | const ret = lookupCalleeReturnType(expr, ref, context); |
| 843 | if (ret) return ret; |
| 844 | |
| 845 | // Direct construction — the callee itself names a class/struct. |
| 846 | if (cppClassExists(expr, ref, context)) return cppLastSegment(expr); |
| 847 | |
| 848 | return null; |
| 849 | } |
| 850 | |
| 851 | /** |
| 852 | * Recover the type of an `auto`-declared local from its initializer on the |
no test coverage detected