gitnexus 1.6.5-rc.9 → 1.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/dist/_shared/scope-resolution/finalize-algorithm.js +10 -2
  2. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  3. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +26 -0
  4. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
  5. package/dist/_shared/scope-resolution/method-dispatch-index.js +22 -3
  6. package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
  7. package/dist/_shared/scope-resolution/registries/lookup-core.js +18 -1
  8. package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
  9. package/dist/_shared/scope-resolution/symbol-definition.d.ts +2 -0
  10. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  11. package/dist/cli/ai-context.d.ts +1 -0
  12. package/dist/cli/ai-context.js +70 -16
  13. package/dist/cli/analyze.d.ts +30 -2
  14. package/dist/cli/analyze.js +45 -5
  15. package/dist/cli/index.js +8 -1
  16. package/dist/cli/setup.js +18 -0
  17. package/dist/cli/wiki.d.ts +2 -0
  18. package/dist/cli/wiki.js +11 -0
  19. package/dist/core/augmentation/engine.js +24 -4
  20. package/dist/core/incremental/shadow-candidates.d.ts +44 -0
  21. package/dist/core/incremental/shadow-candidates.js +74 -0
  22. package/dist/core/incremental/subgraph-extract.d.ts +64 -0
  23. package/dist/core/incremental/subgraph-extract.js +111 -0
  24. package/dist/core/ingestion/call-processor.d.ts +12 -1
  25. package/dist/core/ingestion/call-processor.js +183 -47
  26. package/dist/core/ingestion/class-extractors/configs/c-cpp.js +38 -0
  27. package/dist/core/ingestion/class-extractors/generic.js +8 -0
  28. package/dist/core/ingestion/class-types.d.ts +15 -0
  29. package/dist/core/ingestion/community-processor.js +18 -0
  30. package/dist/core/ingestion/import-resolvers/standard.d.ts +5 -0
  31. package/dist/core/ingestion/import-resolvers/standard.js +31 -1
  32. package/dist/core/ingestion/import-resolvers/utils.js +4 -0
  33. package/dist/core/ingestion/languages/c-cpp.js +20 -2
  34. package/dist/core/ingestion/languages/cpp/adl.d.ts +141 -0
  35. package/dist/core/ingestion/languages/cpp/adl.js +478 -0
  36. package/dist/core/ingestion/languages/cpp/arity-metadata.d.ts +18 -0
  37. package/dist/core/ingestion/languages/cpp/arity-metadata.js +170 -0
  38. package/dist/core/ingestion/languages/cpp/arity.d.ts +17 -0
  39. package/dist/core/ingestion/languages/cpp/arity.js +31 -0
  40. package/dist/core/ingestion/languages/cpp/captures.d.ts +2 -0
  41. package/dist/core/ingestion/languages/cpp/captures.js +1131 -0
  42. package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +31 -0
  43. package/dist/core/ingestion/languages/cpp/conversion-rank.js +47 -0
  44. package/dist/core/ingestion/languages/cpp/file-local-linkage.d.ts +118 -0
  45. package/dist/core/ingestion/languages/cpp/file-local-linkage.js +266 -0
  46. package/dist/core/ingestion/languages/cpp/header-scan.d.ts +8 -0
  47. package/dist/core/ingestion/languages/cpp/header-scan.js +50 -0
  48. package/dist/core/ingestion/languages/cpp/import-decomposer.d.ts +19 -0
  49. package/dist/core/ingestion/languages/cpp/import-decomposer.js +111 -0
  50. package/dist/core/ingestion/languages/cpp/import-target.d.ts +10 -0
  51. package/dist/core/ingestion/languages/cpp/import-target.js +13 -0
  52. package/dist/core/ingestion/languages/cpp/index.d.ts +11 -0
  53. package/dist/core/ingestion/languages/cpp/index.js +11 -0
  54. package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +67 -0
  55. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +176 -0
  56. package/dist/core/ingestion/languages/cpp/interpret.d.ts +35 -0
  57. package/dist/core/ingestion/languages/cpp/interpret.js +113 -0
  58. package/dist/core/ingestion/languages/cpp/merge-bindings.d.ts +13 -0
  59. package/dist/core/ingestion/languages/cpp/merge-bindings.js +29 -0
  60. package/dist/core/ingestion/languages/cpp/query.d.ts +3 -0
  61. package/dist/core/ingestion/languages/cpp/query.js +508 -0
  62. package/dist/core/ingestion/languages/cpp/range-bindings.d.ts +20 -0
  63. package/dist/core/ingestion/languages/cpp/range-bindings.js +212 -0
  64. package/dist/core/ingestion/languages/cpp/scope-resolver.d.ts +17 -0
  65. package/dist/core/ingestion/languages/cpp/scope-resolver.js +246 -0
  66. package/dist/core/ingestion/languages/cpp/simple-hooks.d.ts +24 -0
  67. package/dist/core/ingestion/languages/cpp/simple-hooks.js +62 -0
  68. package/dist/core/ingestion/languages/cpp/two-phase-lookup.d.ts +76 -0
  69. package/dist/core/ingestion/languages/cpp/two-phase-lookup.js +195 -0
  70. package/dist/core/ingestion/languages/java/arity-metadata.d.ts +18 -0
  71. package/dist/core/ingestion/languages/java/arity-metadata.js +40 -0
  72. package/dist/core/ingestion/languages/java/arity.d.ts +10 -0
  73. package/dist/core/ingestion/languages/java/arity.js +24 -0
  74. package/dist/core/ingestion/languages/java/cache-stats.d.ts +15 -0
  75. package/dist/core/ingestion/languages/java/cache-stats.js +26 -0
  76. package/dist/core/ingestion/languages/java/captures.d.ts +17 -0
  77. package/dist/core/ingestion/languages/java/captures.js +187 -0
  78. package/dist/core/ingestion/languages/java/import-decomposer.d.ts +18 -0
  79. package/dist/core/ingestion/languages/java/import-decomposer.js +85 -0
  80. package/dist/core/ingestion/languages/java/import-target.d.ts +17 -0
  81. package/dist/core/ingestion/languages/java/import-target.js +100 -0
  82. package/dist/core/ingestion/languages/java/index.d.ts +29 -0
  83. package/dist/core/ingestion/languages/java/index.js +29 -0
  84. package/dist/core/ingestion/languages/java/interpret.d.ts +13 -0
  85. package/dist/core/ingestion/languages/java/interpret.js +131 -0
  86. package/dist/core/ingestion/languages/java/merge-bindings.d.ts +12 -0
  87. package/dist/core/ingestion/languages/java/merge-bindings.js +40 -0
  88. package/dist/core/ingestion/languages/java/query.d.ts +30 -0
  89. package/dist/core/ingestion/languages/java/query.js +192 -0
  90. package/dist/core/ingestion/languages/java/receiver-binding.d.ts +11 -0
  91. package/dist/core/ingestion/languages/java/receiver-binding.js +95 -0
  92. package/dist/core/ingestion/languages/java/scope-resolver.d.ts +50 -0
  93. package/dist/core/ingestion/languages/java/scope-resolver.js +74 -0
  94. package/dist/core/ingestion/languages/java/simple-hooks.d.ts +13 -0
  95. package/dist/core/ingestion/languages/java/simple-hooks.js +34 -0
  96. package/dist/core/ingestion/languages/java.js +11 -0
  97. package/dist/core/ingestion/languages/php/arity-metadata.d.ts +28 -0
  98. package/dist/core/ingestion/languages/php/arity-metadata.js +63 -0
  99. package/dist/core/ingestion/languages/php/arity.d.ts +25 -0
  100. package/dist/core/ingestion/languages/php/arity.js +40 -0
  101. package/dist/core/ingestion/languages/php/cache-stats.d.ts +15 -0
  102. package/dist/core/ingestion/languages/php/cache-stats.js +26 -0
  103. package/dist/core/ingestion/languages/php/captures.d.ts +34 -0
  104. package/dist/core/ingestion/languages/php/captures.js +739 -0
  105. package/dist/core/ingestion/languages/php/import-decomposer.d.ts +28 -0
  106. package/dist/core/ingestion/languages/php/import-decomposer.js +265 -0
  107. package/dist/core/ingestion/languages/php/import-target.d.ts +47 -0
  108. package/dist/core/ingestion/languages/php/import-target.js +100 -0
  109. package/dist/core/ingestion/languages/php/index.d.ts +68 -0
  110. package/dist/core/ingestion/languages/php/index.js +72 -0
  111. package/dist/core/ingestion/languages/php/interpret.d.ts +36 -0
  112. package/dist/core/ingestion/languages/php/interpret.js +241 -0
  113. package/dist/core/ingestion/languages/php/merge-bindings.d.ts +19 -0
  114. package/dist/core/ingestion/languages/php/merge-bindings.js +47 -0
  115. package/dist/core/ingestion/languages/php/namespace-siblings.d.ts +51 -0
  116. package/dist/core/ingestion/languages/php/namespace-siblings.js +288 -0
  117. package/dist/core/ingestion/languages/php/query.d.ts +32 -0
  118. package/dist/core/ingestion/languages/php/query.js +326 -0
  119. package/dist/core/ingestion/languages/php/receiver-binding.d.ts +36 -0
  120. package/dist/core/ingestion/languages/php/receiver-binding.js +128 -0
  121. package/dist/core/ingestion/languages/php/scope-resolver.d.ts +23 -0
  122. package/dist/core/ingestion/languages/php/scope-resolver.js +358 -0
  123. package/dist/core/ingestion/languages/php/simple-hooks.d.ts +42 -0
  124. package/dist/core/ingestion/languages/php/simple-hooks.js +111 -0
  125. package/dist/core/ingestion/languages/php.d.ts +0 -7
  126. package/dist/core/ingestion/languages/php.js +15 -0
  127. package/dist/core/ingestion/markdown-processor.js +6 -1
  128. package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
  129. package/dist/core/ingestion/model/symbol-table.js +3 -0
  130. package/dist/core/ingestion/parsing-processor.d.ts +22 -2
  131. package/dist/core/ingestion/parsing-processor.js +123 -50
  132. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +54 -2
  133. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +5 -0
  134. package/dist/core/ingestion/pipeline-phases/parse-impl.js +119 -11
  135. package/dist/core/ingestion/pipeline-phases/parse.d.ts +14 -0
  136. package/dist/core/ingestion/pipeline.d.ts +13 -0
  137. package/dist/core/ingestion/registry-primary-flag.js +2 -0
  138. package/dist/core/ingestion/scope-extractor.js +4 -0
  139. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +167 -0
  140. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +3 -0
  141. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +1 -0
  142. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +12 -0
  143. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +1 -1
  144. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +12 -2
  145. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +16 -0
  146. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +36 -0
  147. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +204 -13
  148. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +1 -1
  149. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +55 -4
  150. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +186 -5
  151. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +10 -1
  152. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +207 -9
  153. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +13 -1
  154. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +6 -0
  155. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +17 -0
  156. package/dist/core/ingestion/scope-resolution/pipeline/run.js +86 -8
  157. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +30 -0
  158. package/dist/core/ingestion/scope-resolution/scope/walkers.js +90 -8
  159. package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
  160. package/dist/core/ingestion/tree-sitter-queries.js +23 -0
  161. package/dist/core/ingestion/utils/ast-helpers.js +6 -1
  162. package/dist/core/ingestion/utils/template-arguments.d.ts +11 -0
  163. package/dist/core/ingestion/utils/template-arguments.js +65 -0
  164. package/dist/core/ingestion/workers/parse-worker.d.ts +3 -0
  165. package/dist/core/ingestion/workers/parse-worker.js +42 -1
  166. package/dist/core/lbug/lbug-adapter.d.ts +39 -0
  167. package/dist/core/lbug/lbug-adapter.js +348 -48
  168. package/dist/core/run-analyze.d.ts +2 -0
  169. package/dist/core/run-analyze.js +323 -29
  170. package/dist/core/search/hybrid-search.d.ts +3 -0
  171. package/dist/core/search/hybrid-search.js +23 -6
  172. package/dist/core/wiki/generator.js +4 -3
  173. package/dist/core/wiki/html-viewer.js +2 -1
  174. package/dist/core/wiki/llm-client.d.ts +4 -0
  175. package/dist/core/wiki/llm-client.js +3 -3
  176. package/dist/core/wiki/mermaid-sanitizer.d.ts +2 -0
  177. package/dist/core/wiki/mermaid-sanitizer.js +100 -0
  178. package/dist/mcp/local/local-backend.js +20 -7
  179. package/dist/storage/file-hash.d.ts +47 -0
  180. package/dist/storage/file-hash.js +86 -0
  181. package/dist/storage/parse-cache.d.ts +73 -0
  182. package/dist/storage/parse-cache.js +253 -0
  183. package/dist/storage/repo-manager.d.ts +41 -1
  184. package/dist/storage/repo-manager.js +61 -6
  185. package/hooks/claude/gitnexus-hook.cjs +42 -4
  186. package/hooks/claude/hook-db-lock-probe.cjs +238 -0
  187. package/hooks/claude/hook-lock.cjs +119 -0
  188. package/hooks/claude/win-rm-list-json.ps1 +76 -0
  189. package/package.json +1 -1
  190. package/scripts/build.js +6 -2
  191. package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +16 -16
  192. package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +16 -16
  193. package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +16 -16
  194. package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +16 -16
  195. package/web/assets/{agent-BpHQleHE.js → agent-D2kLt6Dl.js} +91 -91
  196. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +1 -0
  197. package/web/assets/architectureDiagram-UL44E2DR-DvIkEGkp.js +36 -0
  198. package/web/assets/blockDiagram-7IZFK4PR-B4niSLvR.js +132 -0
  199. package/web/assets/{c4Diagram-DFAF54RM-DeJV1rCn.js → c4Diagram-Y2BXMSZH-DIzEXalR.js} +6 -6
  200. package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +4 -0
  201. package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +1 -0
  202. package/web/assets/{chunk-7RZVMHOQ-BdIU-RGO.js → chunk-3SSMPTDK-BzGeeheI.js} +1 -1
  203. package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +159 -0
  204. package/web/assets/chunk-5IMINLNL-CnTLsXIV.js +1 -0
  205. package/web/assets/chunk-5VCL7Z4A-w1BCx98Z.js +1 -0
  206. package/web/assets/chunk-6764PJDD-ChwMM2z4.js +1 -0
  207. package/web/assets/chunk-67TQ5CYL-CChC2cAv.js +124 -0
  208. package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +10 -0
  209. package/web/assets/chunk-7W6UQGC5-CgFyfZ6k.js +1 -0
  210. package/web/assets/chunk-AQ6EADP3-CCFje6lL.js +1 -0
  211. package/web/assets/{chunk-KSICW3F5-C2tZmXwv.js → chunk-AZZRMDJM-5E9ARdDQ.js} +1 -1
  212. package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +1 -0
  213. package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +1 -0
  214. package/web/assets/chunk-INKRHTLW-ELpfuk9h.js +70 -0
  215. package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +1 -0
  216. package/web/assets/{chunk-AEOMTBSW-D7qjBMHW.js → chunk-JQRUD6KW-Dcq_Qnyy.js} +1 -1
  217. package/web/assets/chunk-KGFNY3KK-W-VR57xb.js +62 -0
  218. package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +1 -0
  219. package/web/assets/chunk-KNLZD3CH-BuZBOcso.js +1 -0
  220. package/web/assets/chunk-KRXBNO2N-DH2NPM7I.js +1 -0
  221. package/web/assets/chunk-LCXTWHL2-CqJ0oo1x.js +231 -0
  222. package/web/assets/chunk-LII3EMHJ-3X33tCpU.js +1 -0
  223. package/web/assets/chunk-QA3QBVWF-D5Ha3GgB.js +2 -0
  224. package/web/assets/chunk-RERM46MO-DQNbXtfw.js +1 -0
  225. package/web/assets/chunk-RG4AUYOV-D0M6vdq9.js +206 -0
  226. package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +1 -0
  227. package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +1 -0
  228. package/web/assets/chunk-T2UQINTJ-kGYG7ppP.js +1 -0
  229. package/web/assets/chunk-T5OCTHI4--9wWpVws.js +1 -0
  230. package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +1 -0
  231. package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +1 -0
  232. package/web/assets/chunk-UY5QBCOK-Du-c56gs.js +1 -0
  233. package/web/assets/chunk-W44A43WB-lrCpuupA.js +1 -0
  234. package/web/assets/chunk-ZXARS5L4-CSZRiyOf.js +1 -0
  235. package/web/assets/classDiagram-KGZ6W3CR-BB-saqC1.js +1 -0
  236. package/web/assets/classDiagram-v2-72OJOZXJ-Bp2bAlS5.js +1 -0
  237. package/web/assets/cose-bilkent-UX7MHV2Q-BHv2bbtl.js +1 -0
  238. package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +4 -0
  239. package/web/assets/diagram-3NCE3AQN-BUxnDPOY.js +43 -0
  240. package/web/assets/diagram-GF46GFSD-BJTyqqvI.js +24 -0
  241. package/web/assets/diagram-HNR7UZ2L-fUWreZzx.js +3 -0
  242. package/web/assets/diagram-QXG6HAR7-DilMHamP.js +24 -0
  243. package/web/assets/diagram-WEQXMOUZ-8KUrarg1.js +10 -0
  244. package/web/assets/erDiagram-L5TCEMPS-Doj9mSiW.js +85 -0
  245. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +1 -0
  246. package/web/assets/{flowDiagram-OTCZ4VVT-aAZw4c_M.js → flowDiagram-H6V6AXG4-BOSR-i3p.js} +12 -12
  247. package/web/assets/ganttDiagram-JCBTUEKG-BHQssTz6.js +292 -0
  248. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +1 -0
  249. package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +106 -0
  250. package/web/assets/index-j4-NuleT.js +623 -0
  251. package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +1 -0
  252. package/web/assets/infoDiagram-3YFTVSEB-Ce_TvtaV.js +2 -0
  253. package/web/assets/{ishikawaDiagram-YMYX4NHK-BF8AtDaj.js → ishikawaDiagram-BNXS4ZKH-4MXIDCSF.js} +6 -6
  254. package/web/assets/journeyDiagram-M6C3CM3L-DNPYCpvq.js +139 -0
  255. package/web/assets/kanban-definition-75IXJCU3-yYdfm8Kk.js +89 -0
  256. package/web/assets/{katex-GD7MH7QM-CJiOjBBJ.js → katex-K3KEBU37-CrVLz8l7.js} +1 -1
  257. package/web/assets/mindmap-definition-2TDM6QVE-DFNEKM77.js +96 -0
  258. package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +1 -0
  259. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +1 -0
  260. package/web/assets/pieDiagram-CU6KROY3-iZAqpvhd.js +30 -0
  261. package/web/assets/quadrantDiagram-VICAPDV7-bAm6Hi_5.js +7 -0
  262. package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +1 -0
  263. package/web/assets/requirementDiagram-JXO7QTGE-CtDijhnf.js +84 -0
  264. package/web/assets/sankeyDiagram-URQDO5SZ-LFJz53u5.js +40 -0
  265. package/web/assets/sequenceDiagram-VS2MUI6T-BdjvyCHM.js +162 -0
  266. package/web/assets/stateDiagram-7D4R322I-e5odN9fG.js +1 -0
  267. package/web/assets/stateDiagram-v2-36443NZ5-vPsvjR2D.js +1 -0
  268. package/web/assets/timeline-definition-O6YCAMPW-DPAksNQp.js +120 -0
  269. package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +1 -0
  270. package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +1 -0
  271. package/web/assets/vennDiagram-MWXL3ELB-Dtlfdt7J.js +34 -0
  272. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +1 -0
  273. package/web/assets/wardleyDiagram-CUQ6CDDI-B23uRMUC.js +78 -0
  274. package/web/assets/{xychartDiagram-ZHJ5623Y-DZ7fP1_3.js → xychartDiagram-N2JHSOCM-DxwHeksW.js} +6 -6
  275. package/web/index.html +13 -2
  276. package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BUzkWgDl.js +0 -1
  277. package/web/assets/architectureDiagram-EMZXCZ2Q-CXbzok1G.js +0 -36
  278. package/web/assets/blockDiagram-IGV67L2C-DA1QJ4ZB.js +0 -132
  279. package/web/assets/chunk-3GS5O3IE-B8hpnia8.js +0 -231
  280. package/web/assets/chunk-3YCYZ6SJ-B-BVu21C.js +0 -1
  281. package/web/assets/chunk-6NTNNK5N-DW-jYSDr.js +0 -1
  282. package/web/assets/chunk-A34GCYZU-BbZl-IKy.js +0 -1
  283. package/web/assets/chunk-DJ7UZH7F-B5tMfF87.js +0 -1
  284. package/web/assets/chunk-DKKBVRCY-Djm-6K_e.js +0 -4
  285. package/web/assets/chunk-DU5LTGQ6-QPoynYcp.js +0 -1
  286. package/web/assets/chunk-FXACKDTF-jieSmbe2.js +0 -159
  287. package/web/assets/chunk-H3VCZNTA-8EMHZ3SV.js +0 -1
  288. package/web/assets/chunk-HN6EAY2L-CgE_agsD.js +0 -1
  289. package/web/assets/chunk-O5ABG6QK-DEZV1O19.js +0 -1
  290. package/web/assets/chunk-PK6DOVAG-BXv0JnsJ.js +0 -206
  291. package/web/assets/chunk-RNJOYNJ4-BiBkF9dN.js +0 -1
  292. package/web/assets/chunk-RWUO3TPN-DTWzAhQ1.js +0 -1
  293. package/web/assets/chunk-TBF5ZNIQ-BSl6s9lT.js +0 -1
  294. package/web/assets/chunk-TU3PZOEN-DE5Qhc0N.js +0 -1
  295. package/web/assets/chunk-TYMNRAUI-D1NDLIMG.js +0 -1
  296. package/web/assets/chunk-VELTKBKT-C9dVN39o.js +0 -1
  297. package/web/assets/chunk-W7ZLLLMY-Bu-cdLzs.js +0 -1
  298. package/web/assets/chunk-WSB5WSVC-Dor71SOz.js +0 -1
  299. package/web/assets/chunk-XGPFEOL4-CUonLRle.js +0 -1
  300. package/web/assets/classDiagram-PPOCWD7C-Cdd6UdVv.js +0 -1
  301. package/web/assets/classDiagram-v2-23LJLIIU-DNhxY2Ib.js +0 -1
  302. package/web/assets/cose-bilkent-PNC4W37J-DdZq7Qz_.js +0 -1
  303. package/web/assets/dagre-E77IOHMT-Cfj_6e17.js +0 -4
  304. package/web/assets/diagram-H7BISOXX-BNvpsrBv.js +0 -43
  305. package/web/assets/diagram-JC5VWROH-Cn0rtDbJ.js +0 -24
  306. package/web/assets/diagram-LXUTUG65-CHfoVKNm.js +0 -10
  307. package/web/assets/diagram-WEHSV5V5-BLxHksnu.js +0 -24
  308. package/web/assets/erDiagram-GCSMX5X6-DfdN6iqF.js +0 -85
  309. package/web/assets/ganttDiagram-MUNLMDZQ-BEfC_7Or.js +0 -292
  310. package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-B6ZeRLP0.js +0 -1
  311. package/web/assets/gitGraphDiagram-3HKGZ4G3-CG0kC8Q5.js +0 -106
  312. package/web/assets/index-3NUCUW2s.js +0 -886
  313. package/web/assets/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +0 -1
  314. package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +0 -2
  315. package/web/assets/journeyDiagram-SO5T7YLQ-BW8oKa3N.js +0 -139
  316. package/web/assets/kanban-definition-LJHFXRCJ-DzbOsR-2.js +0 -89
  317. package/web/assets/mindmap-definition-2EUWGEK5-BIXGQALq.js +0 -96
  318. package/web/assets/packet-4T2RLAQJ-EV4IVRXR-Bs7ysNMU.js +0 -1
  319. package/web/assets/pie-ZZUOXDRM-N23DN5KN-Csi8nnbH.js +0 -1
  320. package/web/assets/pieDiagram-3IATQBI2-QY-u7P6a.js +0 -30
  321. package/web/assets/quadrantDiagram-E256RVCF-Di4aNiU8.js +0 -7
  322. package/web/assets/radar-PYXPWWZC-P6TP7ZYP-DJlyXh2-.js +0 -1
  323. package/web/assets/requirementDiagram-M5DCFWZL-CzUUrhQD.js +0 -84
  324. package/web/assets/sankeyDiagram-L3NBLAOT-D2fbMiIU.js +0 -10
  325. package/web/assets/sequenceDiagram-ZOUHS735-BNdkqguh.js +0 -157
  326. package/web/assets/stateDiagram-MLPALWAM-51_Q2w2L.js +0 -1
  327. package/web/assets/stateDiagram-v2-B5LQ5ZB2-8nHs2aNE.js +0 -1
  328. package/web/assets/timeline-definition-5SPVSISX-DkMiGj4Z.js +0 -120
  329. package/web/assets/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +0 -1
  330. package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +0 -1
  331. package/web/assets/vennDiagram-IE5QUKF5-BCxMmf9q.js +0 -34
  332. package/web/assets/wardley-RL74JXVD-BCRCBASE-CMStJhpn.js +0 -1
  333. package/web/assets/wardleyDiagram-XU3VSMPF-ijlLF77s.js +0 -20
  334. /package/web/assets/{context-builder-CqQNhRj1.js → context-builder-_HS0v2ma.js} +0 -0
@@ -13,14 +13,65 @@
13
13
  * 2. Exact-required-match wins over variadic. Variadic is detected
14
14
  * via a `parameterTypes` entry equal to `'params'` or starting
15
15
  * with `'params '` (C# `params` / variadic marker).
16
- * 3. If the arity filter empties the set, fall back to the full
17
- * overload list rather than returning nothing — the caller still
18
- * needs a best-effort candidate.
16
+ * 3. If the arity filter empties the set AND any candidate had
17
+ * unknown bounds (both `parameterCount` and `requiredParameterCount`
18
+ * undefined), fall back to the full overload list — the empty
19
+ * result may be due to missing metadata rather than a real mismatch.
20
+ * If EVERY rejected candidate had definite arity bounds, trust the
21
+ * filter and return empty — the call is genuinely arity-incompatible
22
+ * (e.g., PHP `f(int $req, ...$rest)` called with zero args).
19
23
  * 4. If `argTypes` is present, filter further by per-slot type
20
24
  * equality. An empty string in `argTypes[i]` means "unknown" and
21
25
  * counts as a match. Mismatches disqualify. A non-empty typed
22
26
  * result wins; otherwise return the arity-filtered candidates.
27
+ * 4b. When the exact-type filter from step 4 returns empty AND a
28
+ * `conversionRankFn` is provided, rank candidates via pairwise
29
+ * dominance comparison (ISO C++ [over.ics.rank]): F1 beats F2
30
+ * only when F1 is not worse for every arg and better for at
31
+ * least one. Non-dominated candidates are returned; multiple
32
+ * survivors are genuinely ambiguous.
23
33
  * 5. Empty input returns empty output.
24
34
  */
25
35
  import type { SymbolDefinition } from '../../../../_shared/index.js';
26
- export declare function narrowOverloadCandidates(overloads: readonly SymbolDefinition[], argCount: number | undefined, argTypes: readonly string[] | undefined): readonly SymbolDefinition[];
36
+ /**
37
+ * Per-slot conversion-rank function. Returns a numeric cost for
38
+ * converting `argType` to `paramType`:
39
+ * - 0 = exact match (no conversion)
40
+ * - 1 = promotion (e.g. char→int, bool→int in C++)
41
+ * - 2 = standard conversion (e.g. int→double)
42
+ * - Infinity = incompatible types
43
+ *
44
+ * Each language provides its own implementation. The function operates
45
+ * on normalized type strings (output of the language's type normalizer).
46
+ */
47
+ export type ConversionRankFn = (argType: string, paramType: string) => number;
48
+ export declare function narrowOverloadCandidates(overloads: readonly SymbolDefinition[], argCount: number | undefined, argTypes: readonly string[] | undefined, conversionRankFn?: ConversionRankFn): readonly SymbolDefinition[];
49
+ /**
50
+ * Detect when >1 candidate share identical `parameterTypes` after the
51
+ * per-language normalizer has collapsed distinct underlying types. This
52
+ * signals "the resolver cannot pick the right overload — the
53
+ * normalization that helps single-candidate flows now hides a real
54
+ * ambiguity" and lets callers suppress the edge rather than pick
55
+ * arbitrarily.
56
+ *
57
+ * Concrete trigger (PR #1520 review follow-up plan U2, Claude review
58
+ * Finding 5): the C++ `arity-metadata.ts` normalizer collapses `int`,
59
+ * `long`, `short`, `unsigned`, and `size_t` to `'int'`. Without this
60
+ * check, `process(int)` and `process(long)` both end up with
61
+ * `parameterTypes === ['int']`, and `pickOverload` arbitrarily picks
62
+ * the first — emitting a false CALLS edge to the wrong overload.
63
+ *
64
+ * Returns false when:
65
+ * - 0 or 1 candidates (no ambiguity to detect)
66
+ * - any candidate has undefined `parameterTypes` (can't compare)
67
+ * - candidates differ in arity or in any parameter-type slot
68
+ *
69
+ * Other languages: this check is a precondition gate, not a behavior
70
+ * change for normal narrowing. Languages whose normalizers do not
71
+ * collapse distinct types (verified by grep over `*-arity-metadata.ts`
72
+ * — no `int → int` collapse outside C++) will never produce >1
73
+ * candidate with identical `parameterTypes` from genuinely distinct
74
+ * declarations, so this returns false for them. The branch is
75
+ * effectively C++-only in practice.
76
+ */
77
+ export declare function isOverloadAmbiguousAfterNormalization(candidates: readonly SymbolDefinition[], argCount?: number): boolean;
@@ -13,16 +13,26 @@
13
13
  * 2. Exact-required-match wins over variadic. Variadic is detected
14
14
  * via a `parameterTypes` entry equal to `'params'` or starting
15
15
  * with `'params '` (C# `params` / variadic marker).
16
- * 3. If the arity filter empties the set, fall back to the full
17
- * overload list rather than returning nothing — the caller still
18
- * needs a best-effort candidate.
16
+ * 3. If the arity filter empties the set AND any candidate had
17
+ * unknown bounds (both `parameterCount` and `requiredParameterCount`
18
+ * undefined), fall back to the full overload list — the empty
19
+ * result may be due to missing metadata rather than a real mismatch.
20
+ * If EVERY rejected candidate had definite arity bounds, trust the
21
+ * filter and return empty — the call is genuinely arity-incompatible
22
+ * (e.g., PHP `f(int $req, ...$rest)` called with zero args).
19
23
  * 4. If `argTypes` is present, filter further by per-slot type
20
24
  * equality. An empty string in `argTypes[i]` means "unknown" and
21
25
  * counts as a match. Mismatches disqualify. A non-empty typed
22
26
  * result wins; otherwise return the arity-filtered candidates.
27
+ * 4b. When the exact-type filter from step 4 returns empty AND a
28
+ * `conversionRankFn` is provided, rank candidates via pairwise
29
+ * dominance comparison (ISO C++ [over.ics.rank]): F1 beats F2
30
+ * only when F1 is not worse for every arg and better for at
31
+ * least one. Non-dominated candidates are returned; multiple
32
+ * survivors are genuinely ambiguous.
23
33
  * 5. Empty input returns empty output.
24
34
  */
25
- export function narrowOverloadCandidates(overloads, argCount, argTypes) {
35
+ export function narrowOverloadCandidates(overloads, argCount, argTypes, conversionRankFn) {
26
36
  if (overloads.length === 0)
27
37
  return [];
28
38
  const arityMatches = argCount === undefined
@@ -31,6 +41,16 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes) {
31
41
  const max = d.parameterCount;
32
42
  const min = d.requiredParameterCount;
33
43
  if (max !== undefined && argCount > max) {
44
+ // Variadic marker check is C#-specific (the 'params' keyword).
45
+ // Other languages use their own marker — PHP uses '...' (see
46
+ // `languages/php/arity-metadata.ts:46`), Python uses '*args'-
47
+ // shaped metadata that lives outside `parameterTypes` entirely.
48
+ // This branch is dead code for those languages because they
49
+ // set `parameterCount = undefined` for variadic functions,
50
+ // which keeps `max` undefined and skips this check entirely.
51
+ // Adding new variadic markers here changes behavior for those
52
+ // other languages too — don't extend without auditing each
53
+ // adapter's `arity-metadata.ts`. Finding 9 of PR #1497.
34
54
  const variadic = d.parameterTypes !== undefined &&
35
55
  d.parameterTypes.some((t) => t === 'params' || t.startsWith('params '));
36
56
  if (!variadic)
@@ -40,7 +60,13 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes) {
40
60
  return false;
41
61
  return true;
42
62
  });
43
- const candidates = arityMatches.length > 0 ? arityMatches : overloads;
63
+ // When the arity filter empties the set, only fall back to the full
64
+ // overload list if some candidate had unknown bounds — otherwise the
65
+ // empty result is authoritative (every candidate definitively failed
66
+ // arity, e.g., PHP variadic with required-prefix called with too few
67
+ // args).
68
+ const anyUnknownBounds = overloads.some((d) => d.parameterCount === undefined && d.requiredParameterCount === undefined);
69
+ const candidates = arityMatches.length > 0 ? arityMatches : anyUnknownBounds ? overloads : [];
44
70
  if (argTypes !== undefined && argTypes.length > 0) {
45
71
  const typed = candidates.filter((d) => {
46
72
  const params = d.parameterTypes;
@@ -56,6 +82,161 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes) {
56
82
  });
57
83
  if (typed.length > 0)
58
84
  return typed;
85
+ // ── Conversion-rank scoring (step 4b) ──────────────────────────
86
+ // The exact-type filter above rejected every candidate. When a
87
+ // per-language conversion-rank function is available, rank via
88
+ // pairwise dominance: F1 beats F2 only when F1 is not worse for
89
+ // every arg and better for at least one. Non-dominated candidates
90
+ // are returned; multiple survivors are genuinely ambiguous.
91
+ if (conversionRankFn !== undefined) {
92
+ const ranked = rankByConversion(candidates, argTypes, conversionRankFn);
93
+ if (ranked.length > 0)
94
+ return ranked;
95
+ }
59
96
  }
60
97
  return candidates;
61
98
  }
99
+ /**
100
+ * Pairwise dominance comparison (ISO C++ [over.ics.rank]).
101
+ *
102
+ * F1 is a better match than F2 when F1's conversion rank is **not
103
+ * worse** for every argument AND **strictly better** for at least one.
104
+ * Candidates dominated by any other viable candidate are removed.
105
+ * If more than one non-dominated candidate remains, they are genuinely
106
+ * ambiguous — callers suppress the edge rather than picking arbitrarily.
107
+ *
108
+ * Candidates with at least one `Infinity`-ranked slot (incompatible
109
+ * type) are excluded before pairwise comparison begins.
110
+ */
111
+ function rankByConversion(candidates, argTypes, rankFn) {
112
+ // Step 1: compute per-slot ranks and exclude non-viable candidates.
113
+ const viable = [];
114
+ for (const d of candidates) {
115
+ const params = d.parameterTypes;
116
+ if (params === undefined)
117
+ continue;
118
+ const ranks = [];
119
+ let ok = true;
120
+ for (let i = 0; i < argTypes.length && i < params.length; i++) {
121
+ if (argTypes[i] === '') {
122
+ ranks.push(0); // unknown arg → any-match (rank 0)
123
+ continue;
124
+ }
125
+ const r = rankFn(argTypes[i], params[i]);
126
+ if (!isFinite(r)) {
127
+ ok = false;
128
+ break;
129
+ }
130
+ ranks.push(r);
131
+ }
132
+ if (!ok)
133
+ continue;
134
+ viable.push({ def: d, ranks });
135
+ }
136
+ if (viable.length <= 1)
137
+ return viable.map((v) => v.def);
138
+ // Step 2: pairwise dominance — remove candidates dominated by any other.
139
+ const dominated = new Set();
140
+ for (let i = 0; i < viable.length; i++) {
141
+ if (dominated.has(i))
142
+ continue;
143
+ for (let j = i + 1; j < viable.length; j++) {
144
+ if (dominated.has(j))
145
+ continue;
146
+ const cmp = pairwiseCompare(viable[i].ranks, viable[j].ranks);
147
+ if (cmp < 0)
148
+ dominated.add(j); // i dominates j
149
+ else if (cmp > 0)
150
+ dominated.add(i); // j dominates i
151
+ }
152
+ }
153
+ return viable.filter((_, idx) => !dominated.has(idx)).map((v) => v.def);
154
+ }
155
+ /**
156
+ * Compare two per-slot rank vectors.
157
+ * Returns -1 if `a` dominates `b` (not worse everywhere, better somewhere),
158
+ * +1 if `b` dominates `a`,
159
+ * 0 if neither dominates (incomparable or equal).
160
+ */
161
+ function pairwiseCompare(a, b) {
162
+ let aBetter = false;
163
+ let bBetter = false;
164
+ const len = Math.min(a.length, b.length);
165
+ for (let i = 0; i < len; i++) {
166
+ if (a[i] < b[i])
167
+ aBetter = true;
168
+ else if (b[i] < a[i])
169
+ bBetter = true;
170
+ if (aBetter && bBetter)
171
+ return 0; // incomparable — early exit
172
+ }
173
+ if (aBetter && !bBetter)
174
+ return -1;
175
+ if (bBetter && !aBetter)
176
+ return 1;
177
+ return 0;
178
+ }
179
+ /**
180
+ * Detect when >1 candidate share identical `parameterTypes` after the
181
+ * per-language normalizer has collapsed distinct underlying types. This
182
+ * signals "the resolver cannot pick the right overload — the
183
+ * normalization that helps single-candidate flows now hides a real
184
+ * ambiguity" and lets callers suppress the edge rather than pick
185
+ * arbitrarily.
186
+ *
187
+ * Concrete trigger (PR #1520 review follow-up plan U2, Claude review
188
+ * Finding 5): the C++ `arity-metadata.ts` normalizer collapses `int`,
189
+ * `long`, `short`, `unsigned`, and `size_t` to `'int'`. Without this
190
+ * check, `process(int)` and `process(long)` both end up with
191
+ * `parameterTypes === ['int']`, and `pickOverload` arbitrarily picks
192
+ * the first — emitting a false CALLS edge to the wrong overload.
193
+ *
194
+ * Returns false when:
195
+ * - 0 or 1 candidates (no ambiguity to detect)
196
+ * - any candidate has undefined `parameterTypes` (can't compare)
197
+ * - candidates differ in arity or in any parameter-type slot
198
+ *
199
+ * Other languages: this check is a precondition gate, not a behavior
200
+ * change for normal narrowing. Languages whose normalizers do not
201
+ * collapse distinct types (verified by grep over `*-arity-metadata.ts`
202
+ * — no `int → int` collapse outside C++) will never produce >1
203
+ * candidate with identical `parameterTypes` from genuinely distinct
204
+ * declarations, so this returns false for them. The branch is
205
+ * effectively C++-only in practice.
206
+ */
207
+ export function isOverloadAmbiguousAfterNormalization(candidates, argCount) {
208
+ if (candidates.length < 2)
209
+ return false;
210
+ const first = candidates[0].parameterTypes;
211
+ if (first === undefined)
212
+ return false;
213
+ // When argCount is provided, compare only the first `argCount` slots —
214
+ // this catches default-argument ambiguity: `void f(int); void f(int, int = 0);`
215
+ // called with `f(1)` (argCount=1) leaves both candidates viable because
216
+ // default args make them arity-compatible, and their first slot is
217
+ // identical even though full parameterTypes lengths differ.
218
+ // Without argCount, fall back to full-sequence comparison (the original
219
+ // int/long normalization-collapse case).
220
+ const compareUpTo = argCount !== undefined ? argCount : first.length;
221
+ if (compareUpTo === 0)
222
+ return false;
223
+ if (first.length < compareUpTo)
224
+ return false;
225
+ for (let i = 1; i < candidates.length; i++) {
226
+ const p = candidates[i].parameterTypes;
227
+ if (p === undefined)
228
+ return false;
229
+ if (p.length < compareUpTo)
230
+ return false;
231
+ for (let j = 0; j < compareUpTo; j++) {
232
+ if (p[j] !== first[j])
233
+ return false;
234
+ }
235
+ // When argCount is NOT provided, also require length equality so
236
+ // distinct-arity candidates that happen to share a prefix don't
237
+ // collapse to ambiguous (preserves the original int/long contract).
238
+ if (argCount === undefined && p.length !== first.length)
239
+ return false;
240
+ }
241
+ return true;
242
+ }
@@ -41,6 +41,15 @@ import type { WorkspaceResolutionIndex } from '../workspace-index.js';
41
41
  /** Subset of `ScopeResolver` consumed by this pass. Accepting the
42
42
  * subset rather than the full provider keeps tests and partial
43
43
  * refactors lighter — callers only need to populate what we read. */
44
- type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'unwrapCollectionAccessor' | 'hoistTypeBindingsToModule'>;
44
+ type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'unwrapCollectionAccessor' | 'hoistTypeBindingsToModule' | 'resolveQualifiedReceiverMember' | 'resolveThisViaEnclosingClass' | 'conversionRankFn'>;
45
45
  export declare function emitReceiverBoundCalls(graph: KnowledgeGraph, scopes: ScopeResolutionIndexes, parsedFiles: readonly ParsedFile[], nodeLookup: GraphNodeLookup, handledSites: Set<string>, provider: ReceiverBoundProviderSubset, index: WorkspaceResolutionIndex, model: SemanticModel): number;
46
+ /**
47
+ * Sentinel returned by `pickOverload` when narrowing leaves >1 candidate
48
+ * sharing identical normalized parameter-types. Callers should suppress
49
+ * the CALLS edge AND mark the site as handled so `emitReferencesViaLookup`
50
+ * does not re-emit from the pre-resolved reference index. See
51
+ * `pickOverload` JSDoc for the upstream cause (per-language normalizer
52
+ * collapses distinct types in arity-metadata).
53
+ */
54
+ export declare const OVERLOAD_AMBIGUOUS: unique symbol;
46
55
  export {};
@@ -36,7 +36,49 @@ import { findClassBindingInScope, findEnclosingClassDef, findExportedDef, findOw
36
36
  import { tryEmitEdge } from '../graph-bridge/edges.js';
37
37
  import { resolveCompoundReceiverClass } from '../passes/compound-receiver.js';
38
38
  import { resolveDefGraphId } from '../graph-bridge/ids.js';
39
- import { narrowOverloadCandidates } from './overload-narrowing.js';
39
+ import { narrowOverloadCandidates, isOverloadAmbiguousAfterNormalization, } from './overload-narrowing.js';
40
+ import { extractTemplateArguments, stripTemplateArguments, } from '../../utils/template-arguments.js';
41
+ function normalizeTemplateArgToken(value) {
42
+ return value.replace(/\s+/g, '');
43
+ }
44
+ function resolveClassBindingForName(scopeId, rawClassName, scopes) {
45
+ const direct = findClassBindingInScope(scopeId, rawClassName, scopes);
46
+ if (direct !== undefined)
47
+ return direct;
48
+ if (!rawClassName.includes('<'))
49
+ return undefined;
50
+ const baseName = stripTemplateArguments(rawClassName).replace(/\s+/g, '');
51
+ if (baseName.length === 0)
52
+ return undefined;
53
+ const wantedArgs = extractTemplateArguments(rawClassName)?.map(normalizeTemplateArgToken);
54
+ if (wantedArgs !== undefined && wantedArgs.length > 0) {
55
+ // qualifiedNames is a Map and may not contain the stripped base name at all
56
+ // (e.g., unresolved type binding or only template-qualified entries), so
57
+ // default to [] before checking `.length`.
58
+ const qnameIds = scopes.qualifiedNames.get(baseName) ?? [];
59
+ if (qnameIds.length === 0) {
60
+ return findClassBindingInScope(scopeId, baseName, scopes);
61
+ }
62
+ const matches = [];
63
+ for (const id of qnameIds) {
64
+ const def = scopes.defs.get(id);
65
+ if (def === undefined || !isClassLike(def.type))
66
+ continue;
67
+ const defArgs = def.templateArguments?.map(normalizeTemplateArgToken);
68
+ if (defArgs !== undefined &&
69
+ defArgs.length === wantedArgs.length &&
70
+ defArgs.every((value, i) => value === wantedArgs[i])) {
71
+ matches.push(def);
72
+ }
73
+ }
74
+ if (matches.length === 1)
75
+ return matches[0];
76
+ // Scope extractor only records class definitions with bodies in C++, so
77
+ // forward declarations are not expected here. Keep fallback behavior for
78
+ // safety in non-ODR or mixed-language edge cases.
79
+ }
80
+ return findClassBindingInScope(scopeId, baseName, scopes);
81
+ }
40
82
  export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, handledSites, provider, index, model) {
41
83
  let emitted = 0;
42
84
  // Per-pass dedup so the multiple cases don't double-emit if two of
@@ -113,10 +155,24 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
113
155
  const memberName = site.name;
114
156
  const siteKey = `${parsed.filePath}:${site.atRange.startLine}:${site.atRange.startCol}`;
115
157
  // ── super branch ─────────────────────────────────────────────
116
- if (provider.isSuperReceiver(receiverName)) {
158
+ // Languages with caller-context-dependent super classification
159
+ // (C++) define `isSuperReceiverInContext`; we prefer it. Simple
160
+ // text-only languages (Python, Java, PHP) use the plain hook.
161
+ const isSuper = provider.isSuperReceiverInContext !== undefined
162
+ ? provider.isSuperReceiverInContext(receiverName, site.inScope, scopes)
163
+ : provider.isSuperReceiver(receiverName);
164
+ if (isSuper) {
117
165
  const enclosingClass = findEnclosingClassDef(site.inScope, scopes);
118
166
  if (enclosingClass !== undefined) {
119
- const ancestors = scopes.methodDispatch.mroFor(enclosingClass.nodeId);
167
+ // For super-receiver dispatch (`parent::`, `base.`, `super()`),
168
+ // walk the inheritance-only ancestor chain when the language
169
+ // exposes it. PHP's `parent::` semantically bypasses composed
170
+ // traits; other languages without mixin augmentation have no
171
+ // `extendsOnlyMroFor` and fall back to `mroFor`.
172
+ const extendsOnly = scopes.methodDispatch.extendsOnlyMroFor;
173
+ const ancestors = extendsOnly !== undefined
174
+ ? extendsOnly(enclosingClass.nodeId)
175
+ : scopes.methodDispatch.mroFor(enclosingClass.nodeId);
120
176
  let memberDef;
121
177
  for (const ownerId of ancestors) {
122
178
  memberDef = findOwnedMember(ownerId, memberName, model);
@@ -176,6 +232,78 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
176
232
  }
177
233
  }
178
234
  }
235
+ // ── Case 0.5: implicit `this` receiver ───────────────────────
236
+ // C++ `this->member()` (and same-shape receivers in other OO
237
+ // languages) should resolve against the enclosing class + MRO
238
+ // even when there is no explicit `this` typeBinding in scope.
239
+ if (provider.resolveThisViaEnclosingClass === true && receiverName === 'this') {
240
+ const enclosingClass = findEnclosingClassDef(site.inScope, scopes);
241
+ if (enclosingClass !== undefined) {
242
+ const chain = [
243
+ enclosingClass.nodeId,
244
+ ...scopes.methodDispatch.mroFor(enclosingClass.nodeId),
245
+ ];
246
+ let memberDef;
247
+ let ambiguous = false;
248
+ let hiddenByName = false;
249
+ for (const ownerId of chain) {
250
+ const methodOverloads = model.methods.lookupAllByOwner(ownerId, memberName);
251
+ if (methodOverloads.length > 0) {
252
+ const narrowed = narrowOverloadCandidates(methodOverloads, site.arity, site.argumentTypes, provider.conversionRankFn);
253
+ if (isOverloadAmbiguousAfterNormalization(narrowed, site.arity)) {
254
+ ambiguous = true;
255
+ break;
256
+ }
257
+ if (narrowed.length === 0) {
258
+ // C++ name hiding: if the derived class declares `f`, base-class
259
+ // overloads named `f` are hidden for member lookup
260
+ // ([basic.lookup.classref]). A non-viable derived overload set
261
+ // therefore terminates lookup instead of falling through to base.
262
+ hiddenByName = true;
263
+ break;
264
+ }
265
+ // Multiple tied survivors with distinct param types (e.g.
266
+ // h(int,double) vs h(double,int) both scoring 2) → ambiguous.
267
+ if (narrowed.length > 1) {
268
+ ambiguous = true;
269
+ break;
270
+ }
271
+ memberDef = narrowed[0] ?? methodOverloads[0];
272
+ break;
273
+ }
274
+ // Field/property lookup intentionally runs only after the method
275
+ // lookup above: in C++ member-name lookup, functions with this
276
+ // name hide same-named base members; we therefore prefer method
277
+ // candidates first and only target a field when no methods with
278
+ // this name exist on the current owner.
279
+ memberDef = model.fields.lookupFieldByOwner(ownerId, memberName);
280
+ if (memberDef !== undefined) {
281
+ break;
282
+ }
283
+ }
284
+ if (ambiguous) {
285
+ handledSites.add(siteKey);
286
+ continue;
287
+ }
288
+ if (hiddenByName) {
289
+ handledSites.add(siteKey);
290
+ continue;
291
+ }
292
+ if (memberDef !== undefined) {
293
+ const reason = site.kind === 'write' || site.kind === 'read'
294
+ ? site.kind
295
+ : memberDef.filePath !== parsed.filePath
296
+ ? 'import-resolved'
297
+ : 'global';
298
+ const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
299
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse);
300
+ if (ok)
301
+ emitted++;
302
+ handledSites.add(siteKey);
303
+ continue;
304
+ }
305
+ }
306
+ }
179
307
  // ── Case 1: namespace receiver ───────────────────────────────
180
308
  const targetFiles = namespaceTargets.get(receiverName);
181
309
  if (targetFiles !== undefined) {
@@ -194,6 +322,28 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
194
322
  if (found)
195
323
  continue;
196
324
  }
325
+ // ── Case 1.5: qualified namespace-receiver (language-specific) ───
326
+ // Languages whose qualified-name semantics need workspace-wide
327
+ // namespace-scope walking (C++ `outer::foo()`, including inline-
328
+ // namespace transitive traversal) implement `resolveQualifiedReceiverMember`.
329
+ // Runs before Case 2 so namespace receivers don't accidentally match a
330
+ // class with the same simple name.
331
+ if (provider.resolveQualifiedReceiverMember !== undefined) {
332
+ const memberDef = provider.resolveQualifiedReceiverMember(receiverName, memberName, site.inScope, scopes, parsedFiles);
333
+ if (memberDef === 'ambiguous') {
334
+ // Same-name ambiguity across inline-namespace children (#1564):
335
+ // suppress edge emission, mark site handled.
336
+ handledSites.add(siteKey);
337
+ continue;
338
+ }
339
+ if (memberDef !== undefined) {
340
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse);
341
+ if (ok)
342
+ emitted++;
343
+ handledSites.add(siteKey);
344
+ continue;
345
+ }
346
+ }
197
347
  // ── Case 2: class-name receiver ──────────────────────────────
198
348
  const classDef = findClassBindingInScope(site.inScope, receiverName, scopes);
199
349
  if (classDef !== undefined) {
@@ -201,8 +351,19 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
201
351
  let memberDef;
202
352
  for (const ownerId of chain) {
203
353
  memberDef = findOwnedMember(ownerId, memberName, model);
204
- if (memberDef !== undefined)
354
+ if (memberDef !== undefined) {
355
+ // The MRO chain is most-derived-first ([classDef, ...ancestors]).
356
+ // If the most-derived definition is arity-incompatible with the
357
+ // call site, PHP throws ArgumentCountError at runtime — it does
358
+ // NOT silently dispatch to an ancestor. Terminate the chain walk
359
+ // so no edge is emitted, rather than falling through to an
360
+ // arity-compatible ancestor (which would be a false positive).
361
+ if (narrowOverloadCandidates([memberDef], site.arity, site.argumentTypes).length === 0) {
362
+ memberDef = undefined;
363
+ break;
364
+ }
205
365
  break;
366
+ }
206
367
  }
207
368
  if (memberDef !== undefined) {
208
369
  const reason = site.kind === 'write' || site.kind === 'read'
@@ -281,7 +442,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
281
442
  }
282
443
  // ── Case 4: simple typeBinding (`u: U`) ──────────────────────
283
444
  if (typeRef !== undefined && !typeRef.rawName.includes('.')) {
284
- let ownerDef = findClassBindingInScope(site.inScope, typeRef.rawName, scopes);
445
+ let ownerDef = resolveClassBindingForName(site.inScope, typeRef.rawName, scopes);
285
446
  // `findClassBindingInScope(..., typeRef.rawName)` only works when
286
447
  // rawName is itself a class symbol reachable through scope bindings.
287
448
  // For languages with namespace-style imports (Go), imported types
@@ -304,10 +465,24 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
304
465
  if (ownerDef !== undefined) {
305
466
  const chain = [ownerDef.nodeId, ...scopes.methodDispatch.mroFor(ownerDef.nodeId)];
306
467
  let memberDef;
468
+ let ambiguous = false;
307
469
  for (const ownerId of chain) {
308
- memberDef = pickOverload(ownerId, memberName, site, model);
309
- if (memberDef !== undefined)
470
+ const picked = pickOverload(ownerId, memberName, site, model, provider.conversionRankFn);
471
+ if (picked === OVERLOAD_AMBIGUOUS) {
472
+ ambiguous = true;
310
473
  break;
474
+ }
475
+ if (picked !== undefined) {
476
+ memberDef = picked;
477
+ break;
478
+ }
479
+ }
480
+ if (ambiguous) {
481
+ // Suppress and mark handled so `emitReferencesViaLookup`
482
+ // doesn't re-emit the pre-resolved reference. See
483
+ // OVERLOAD_AMBIGUOUS docstring for the upstream cause.
484
+ handledSites.add(siteKey);
485
+ continue;
311
486
  }
312
487
  if (memberDef !== undefined) {
313
488
  // For read/write ACCESSES, mirror the legacy DAG's reason
@@ -343,7 +518,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
343
518
  * types when multiple overloads share the name. Falls back to the
344
519
  * first-seen def (legacy `findOwnedMember` semantics) when there's
345
520
  * no narrowing signal or when `argumentTypes` is unavailable. */
346
- function pickOverload(ownerId, memberName, site, model) {
521
+ function pickOverload(ownerId, memberName, site, model, conversionRankFn) {
347
522
  const overloads = model.methods.lookupAllByOwner(ownerId, memberName);
348
523
  if (overloads.length === 0) {
349
524
  // Non-callable member (field / property / variable) — ACCESSES
@@ -353,6 +528,29 @@ function pickOverload(ownerId, memberName, site, model) {
353
528
  }
354
529
  if (overloads.length === 1)
355
530
  return overloads[0];
356
- const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes);
531
+ const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, conversionRankFn);
532
+ // When narrowing leaves >1 candidate that share identical normalized
533
+ // parameter-types (e.g., C++ `f(int)` vs `f(long)` both collapsed to
534
+ // `['int']` by `normalizeCppParamType`), suppress the edge entirely.
535
+ // The graph schema has no ambiguous-target edge model, so emitting one
536
+ // would arbitrarily pick a candidate and lie about the call's target.
537
+ // PR #1520 review follow-up plan U2 / Claude review Finding 5.
538
+ if (isOverloadAmbiguousAfterNormalization(candidates, site.arity))
539
+ return OVERLOAD_AMBIGUOUS;
540
+ // When conversion-rank scoring leaves >1 tied candidate with distinct
541
+ // parameter types (e.g. h(int,double) vs h(double,int) both scoring 2),
542
+ // suppress rather than picking arbitrarily — C++ would call this
543
+ // ambiguous. Mirrors ADL merged-candidate suppression behavior.
544
+ if (candidates.length > 1)
545
+ return OVERLOAD_AMBIGUOUS;
357
546
  return candidates[0] ?? overloads[0];
358
547
  }
548
+ /**
549
+ * Sentinel returned by `pickOverload` when narrowing leaves >1 candidate
550
+ * sharing identical normalized parameter-types. Callers should suppress
551
+ * the CALLS edge AND mark the site as handled so `emitReferencesViaLookup`
552
+ * does not re-emit from the pre-resolved reference index. See
553
+ * `pickOverload` JSDoc for the upstream cause (per-language normalizer
554
+ * collapses distinct types in arity-metadata).
555
+ */
556
+ export const OVERLOAD_AMBIGUOUS = Symbol('overload-ambiguous');
@@ -63,12 +63,23 @@ export const scopeResolutionPhase = {
63
63
  // Worker-mode parses leave the cache empty for those files; they
64
64
  // also fall back to a fresh parse — no correctness impact.
65
65
  const parseOutput = getPhaseOutput(deps, 'parse');
66
- const { scopeTreeCache, resolutionContext } = parseOutput;
66
+ const { scopeTreeCache, resolutionContext, parsedFiles: workerParsedFiles } = parseOutput;
67
67
  // SemanticModel populated during `parse`: scope-resolution consumes
68
68
  // TypeRegistry / MethodRegistry / SymbolTable lookups instead of
69
69
  // rebuilding parallel indexes. See ARCHITECTURE.md § "Semantic-model
70
70
  // source of truth".
71
71
  const model = resolutionContext.model;
72
+ // Build a per-file lookup of ParsedFile artifacts the workers (or
73
+ // sequential extracts) already produced. Threading this into
74
+ // `runScopeResolution` lets the per-language extract loop short-
75
+ // circuit `extractParsedFile` — the dominant cost on the warm-cache
76
+ // path, since workers can't return tree-sitter Trees across the
77
+ // MessageChannel and scope-resolution would otherwise re-parse
78
+ // every file from scratch on the main thread.
79
+ const preExtractedByPath = new Map();
80
+ for (const pf of workerParsedFiles) {
81
+ preExtractedByPath.set(pf.filePath, pf);
82
+ }
72
83
  let totalFiles = 0;
73
84
  let totalImports = 0;
74
85
  let totalRefs = 0;
@@ -101,6 +112,7 @@ export const scopeResolutionPhase = {
101
112
  files,
102
113
  treeCache: scopeTreeCache,
103
114
  resolutionConfig,
115
+ preExtractedParsedFiles: preExtractedByPath,
104
116
  onWarn: (msg) => {
105
117
  if (isSemanticModelValidatorEnabled()) {
106
118
  logger.warn(`[scope-resolution:${lang}] ${msg}`);
@@ -13,7 +13,10 @@ import { pythonScopeResolver } from '../../languages/python/scope-resolver.js';
13
13
  import { csharpScopeResolver } from '../../languages/csharp/scope-resolver.js';
14
14
  import { typescriptScopeResolver } from '../../languages/typescript/scope-resolver.js';
15
15
  import { goScopeResolver } from '../../languages/go/scope-resolver.js';
16
+ import { javaScopeResolver } from '../../languages/java/scope-resolver.js';
16
17
  import { cScopeResolver } from '../../languages/c/scope-resolver.js';
18
+ import { cppScopeResolver } from '../../languages/cpp/scope-resolver.js';
19
+ import { phpScopeResolver } from '../../languages/php/scope-resolver.js';
17
20
  /** Map of `SupportedLanguages` → `ScopeResolver`. The phase iterates
18
21
  * this map intersected with `MIGRATED_LANGUAGES` (the per-language
19
22
  * flag set) so adding a resolver here without flipping the flag is
@@ -23,5 +26,8 @@ export const SCOPE_RESOLVERS = new Map([
23
26
  [SupportedLanguages.CSharp, csharpScopeResolver],
24
27
  [SupportedLanguages.TypeScript, typescriptScopeResolver],
25
28
  [SupportedLanguages.Go, goScopeResolver],
29
+ [SupportedLanguages.Java, javaScopeResolver],
26
30
  [SupportedLanguages.C, cScopeResolver],
31
+ [SupportedLanguages.CPlusPlus, cppScopeResolver],
32
+ [SupportedLanguages.PHP, phpScopeResolver],
27
33
  ]);