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.
- package/dist/_shared/scope-resolution/finalize-algorithm.js +10 -2
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +26 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/method-dispatch-index.js +22 -3
- package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/lookup-core.js +18 -1
- package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +2 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +1 -0
- package/dist/cli/ai-context.js +70 -16
- package/dist/cli/analyze.d.ts +30 -2
- package/dist/cli/analyze.js +45 -5
- package/dist/cli/index.js +8 -1
- package/dist/cli/setup.js +18 -0
- package/dist/cli/wiki.d.ts +2 -0
- package/dist/cli/wiki.js +11 -0
- package/dist/core/augmentation/engine.js +24 -4
- package/dist/core/incremental/shadow-candidates.d.ts +44 -0
- package/dist/core/incremental/shadow-candidates.js +74 -0
- package/dist/core/incremental/subgraph-extract.d.ts +64 -0
- package/dist/core/incremental/subgraph-extract.js +111 -0
- package/dist/core/ingestion/call-processor.d.ts +12 -1
- package/dist/core/ingestion/call-processor.js +183 -47
- package/dist/core/ingestion/class-extractors/configs/c-cpp.js +38 -0
- package/dist/core/ingestion/class-extractors/generic.js +8 -0
- package/dist/core/ingestion/class-types.d.ts +15 -0
- package/dist/core/ingestion/community-processor.js +18 -0
- package/dist/core/ingestion/import-resolvers/standard.d.ts +5 -0
- package/dist/core/ingestion/import-resolvers/standard.js +31 -1
- package/dist/core/ingestion/import-resolvers/utils.js +4 -0
- package/dist/core/ingestion/languages/c-cpp.js +20 -2
- package/dist/core/ingestion/languages/cpp/adl.d.ts +141 -0
- package/dist/core/ingestion/languages/cpp/adl.js +478 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.d.ts +18 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +170 -0
- package/dist/core/ingestion/languages/cpp/arity.d.ts +17 -0
- package/dist/core/ingestion/languages/cpp/arity.js +31 -0
- package/dist/core/ingestion/languages/cpp/captures.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/captures.js +1131 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +31 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.js +47 -0
- package/dist/core/ingestion/languages/cpp/file-local-linkage.d.ts +118 -0
- package/dist/core/ingestion/languages/cpp/file-local-linkage.js +266 -0
- package/dist/core/ingestion/languages/cpp/header-scan.d.ts +8 -0
- package/dist/core/ingestion/languages/cpp/header-scan.js +50 -0
- package/dist/core/ingestion/languages/cpp/import-decomposer.d.ts +19 -0
- package/dist/core/ingestion/languages/cpp/import-decomposer.js +111 -0
- package/dist/core/ingestion/languages/cpp/import-target.d.ts +10 -0
- package/dist/core/ingestion/languages/cpp/import-target.js +13 -0
- package/dist/core/ingestion/languages/cpp/index.d.ts +11 -0
- package/dist/core/ingestion/languages/cpp/index.js +11 -0
- package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +67 -0
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +176 -0
- package/dist/core/ingestion/languages/cpp/interpret.d.ts +35 -0
- package/dist/core/ingestion/languages/cpp/interpret.js +113 -0
- package/dist/core/ingestion/languages/cpp/merge-bindings.d.ts +13 -0
- package/dist/core/ingestion/languages/cpp/merge-bindings.js +29 -0
- package/dist/core/ingestion/languages/cpp/query.d.ts +3 -0
- package/dist/core/ingestion/languages/cpp/query.js +508 -0
- package/dist/core/ingestion/languages/cpp/range-bindings.d.ts +20 -0
- package/dist/core/ingestion/languages/cpp/range-bindings.js +212 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.d.ts +17 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +246 -0
- package/dist/core/ingestion/languages/cpp/simple-hooks.d.ts +24 -0
- package/dist/core/ingestion/languages/cpp/simple-hooks.js +62 -0
- package/dist/core/ingestion/languages/cpp/two-phase-lookup.d.ts +76 -0
- package/dist/core/ingestion/languages/cpp/two-phase-lookup.js +195 -0
- package/dist/core/ingestion/languages/java/arity-metadata.d.ts +18 -0
- package/dist/core/ingestion/languages/java/arity-metadata.js +40 -0
- package/dist/core/ingestion/languages/java/arity.d.ts +10 -0
- package/dist/core/ingestion/languages/java/arity.js +24 -0
- package/dist/core/ingestion/languages/java/cache-stats.d.ts +15 -0
- package/dist/core/ingestion/languages/java/cache-stats.js +26 -0
- package/dist/core/ingestion/languages/java/captures.d.ts +17 -0
- package/dist/core/ingestion/languages/java/captures.js +187 -0
- package/dist/core/ingestion/languages/java/import-decomposer.d.ts +18 -0
- package/dist/core/ingestion/languages/java/import-decomposer.js +85 -0
- package/dist/core/ingestion/languages/java/import-target.d.ts +17 -0
- package/dist/core/ingestion/languages/java/import-target.js +100 -0
- package/dist/core/ingestion/languages/java/index.d.ts +29 -0
- package/dist/core/ingestion/languages/java/index.js +29 -0
- package/dist/core/ingestion/languages/java/interpret.d.ts +13 -0
- package/dist/core/ingestion/languages/java/interpret.js +131 -0
- package/dist/core/ingestion/languages/java/merge-bindings.d.ts +12 -0
- package/dist/core/ingestion/languages/java/merge-bindings.js +40 -0
- package/dist/core/ingestion/languages/java/query.d.ts +30 -0
- package/dist/core/ingestion/languages/java/query.js +192 -0
- package/dist/core/ingestion/languages/java/receiver-binding.d.ts +11 -0
- package/dist/core/ingestion/languages/java/receiver-binding.js +95 -0
- package/dist/core/ingestion/languages/java/scope-resolver.d.ts +50 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +74 -0
- package/dist/core/ingestion/languages/java/simple-hooks.d.ts +13 -0
- package/dist/core/ingestion/languages/java/simple-hooks.js +34 -0
- package/dist/core/ingestion/languages/java.js +11 -0
- package/dist/core/ingestion/languages/php/arity-metadata.d.ts +28 -0
- package/dist/core/ingestion/languages/php/arity-metadata.js +63 -0
- package/dist/core/ingestion/languages/php/arity.d.ts +25 -0
- package/dist/core/ingestion/languages/php/arity.js +40 -0
- package/dist/core/ingestion/languages/php/cache-stats.d.ts +15 -0
- package/dist/core/ingestion/languages/php/cache-stats.js +26 -0
- package/dist/core/ingestion/languages/php/captures.d.ts +34 -0
- package/dist/core/ingestion/languages/php/captures.js +739 -0
- package/dist/core/ingestion/languages/php/import-decomposer.d.ts +28 -0
- package/dist/core/ingestion/languages/php/import-decomposer.js +265 -0
- package/dist/core/ingestion/languages/php/import-target.d.ts +47 -0
- package/dist/core/ingestion/languages/php/import-target.js +100 -0
- package/dist/core/ingestion/languages/php/index.d.ts +68 -0
- package/dist/core/ingestion/languages/php/index.js +72 -0
- package/dist/core/ingestion/languages/php/interpret.d.ts +36 -0
- package/dist/core/ingestion/languages/php/interpret.js +241 -0
- package/dist/core/ingestion/languages/php/merge-bindings.d.ts +19 -0
- package/dist/core/ingestion/languages/php/merge-bindings.js +47 -0
- package/dist/core/ingestion/languages/php/namespace-siblings.d.ts +51 -0
- package/dist/core/ingestion/languages/php/namespace-siblings.js +288 -0
- package/dist/core/ingestion/languages/php/query.d.ts +32 -0
- package/dist/core/ingestion/languages/php/query.js +326 -0
- package/dist/core/ingestion/languages/php/receiver-binding.d.ts +36 -0
- package/dist/core/ingestion/languages/php/receiver-binding.js +128 -0
- package/dist/core/ingestion/languages/php/scope-resolver.d.ts +23 -0
- package/dist/core/ingestion/languages/php/scope-resolver.js +358 -0
- package/dist/core/ingestion/languages/php/simple-hooks.d.ts +42 -0
- package/dist/core/ingestion/languages/php/simple-hooks.js +111 -0
- package/dist/core/ingestion/languages/php.d.ts +0 -7
- package/dist/core/ingestion/languages/php.js +15 -0
- package/dist/core/ingestion/markdown-processor.js +6 -1
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
- package/dist/core/ingestion/model/symbol-table.js +3 -0
- package/dist/core/ingestion/parsing-processor.d.ts +22 -2
- package/dist/core/ingestion/parsing-processor.js +123 -50
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +54 -2
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +5 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +119 -11
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +14 -0
- package/dist/core/ingestion/pipeline.d.ts +13 -0
- package/dist/core/ingestion/registry-primary-flag.js +2 -0
- package/dist/core/ingestion/scope-extractor.js +4 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +167 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +3 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +1 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +12 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +12 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +16 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +36 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +204 -13
- package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +1 -1
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +55 -4
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +186 -5
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +10 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +207 -9
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +13 -1
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +6 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +17 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +86 -8
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +30 -0
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +90 -8
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +23 -0
- package/dist/core/ingestion/utils/ast-helpers.js +6 -1
- package/dist/core/ingestion/utils/template-arguments.d.ts +11 -0
- package/dist/core/ingestion/utils/template-arguments.js +65 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +3 -0
- package/dist/core/ingestion/workers/parse-worker.js +42 -1
- package/dist/core/lbug/lbug-adapter.d.ts +39 -0
- package/dist/core/lbug/lbug-adapter.js +348 -48
- package/dist/core/run-analyze.d.ts +2 -0
- package/dist/core/run-analyze.js +323 -29
- package/dist/core/search/hybrid-search.d.ts +3 -0
- package/dist/core/search/hybrid-search.js +23 -6
- package/dist/core/wiki/generator.js +4 -3
- package/dist/core/wiki/html-viewer.js +2 -1
- package/dist/core/wiki/llm-client.d.ts +4 -0
- package/dist/core/wiki/llm-client.js +3 -3
- package/dist/core/wiki/mermaid-sanitizer.d.ts +2 -0
- package/dist/core/wiki/mermaid-sanitizer.js +100 -0
- package/dist/mcp/local/local-backend.js +20 -7
- package/dist/storage/file-hash.d.ts +47 -0
- package/dist/storage/file-hash.js +86 -0
- package/dist/storage/parse-cache.d.ts +73 -0
- package/dist/storage/parse-cache.js +253 -0
- package/dist/storage/repo-manager.d.ts +41 -1
- package/dist/storage/repo-manager.js +61 -6
- package/hooks/claude/gitnexus-hook.cjs +42 -4
- package/hooks/claude/hook-db-lock-probe.cjs +238 -0
- package/hooks/claude/hook-lock.cjs +119 -0
- package/hooks/claude/win-rm-list-json.ps1 +76 -0
- package/package.json +1 -1
- package/scripts/build.js +6 -2
- package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +16 -16
- package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +16 -16
- package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +16 -16
- package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +16 -16
- package/web/assets/{agent-BpHQleHE.js → agent-D2kLt6Dl.js} +91 -91
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-DvIkEGkp.js +36 -0
- package/web/assets/blockDiagram-7IZFK4PR-B4niSLvR.js +132 -0
- package/web/assets/{c4Diagram-DFAF54RM-DeJV1rCn.js → c4Diagram-Y2BXMSZH-DIzEXalR.js} +6 -6
- package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +1 -0
- package/web/assets/{chunk-7RZVMHOQ-BdIU-RGO.js → chunk-3SSMPTDK-BzGeeheI.js} +1 -1
- package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +159 -0
- package/web/assets/chunk-5IMINLNL-CnTLsXIV.js +1 -0
- package/web/assets/chunk-5VCL7Z4A-w1BCx98Z.js +1 -0
- package/web/assets/chunk-6764PJDD-ChwMM2z4.js +1 -0
- package/web/assets/chunk-67TQ5CYL-CChC2cAv.js +124 -0
- package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +10 -0
- package/web/assets/chunk-7W6UQGC5-CgFyfZ6k.js +1 -0
- package/web/assets/chunk-AQ6EADP3-CCFje6lL.js +1 -0
- package/web/assets/{chunk-KSICW3F5-C2tZmXwv.js → chunk-AZZRMDJM-5E9ARdDQ.js} +1 -1
- package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +1 -0
- package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +1 -0
- package/web/assets/chunk-INKRHTLW-ELpfuk9h.js +70 -0
- package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +1 -0
- package/web/assets/{chunk-AEOMTBSW-D7qjBMHW.js → chunk-JQRUD6KW-Dcq_Qnyy.js} +1 -1
- package/web/assets/chunk-KGFNY3KK-W-VR57xb.js +62 -0
- package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +1 -0
- package/web/assets/chunk-KNLZD3CH-BuZBOcso.js +1 -0
- package/web/assets/chunk-KRXBNO2N-DH2NPM7I.js +1 -0
- package/web/assets/chunk-LCXTWHL2-CqJ0oo1x.js +231 -0
- package/web/assets/chunk-LII3EMHJ-3X33tCpU.js +1 -0
- package/web/assets/chunk-QA3QBVWF-D5Ha3GgB.js +2 -0
- package/web/assets/chunk-RERM46MO-DQNbXtfw.js +1 -0
- package/web/assets/chunk-RG4AUYOV-D0M6vdq9.js +206 -0
- package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +1 -0
- package/web/assets/chunk-T2UQINTJ-kGYG7ppP.js +1 -0
- package/web/assets/chunk-T5OCTHI4--9wWpVws.js +1 -0
- package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +1 -0
- package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +1 -0
- package/web/assets/chunk-UY5QBCOK-Du-c56gs.js +1 -0
- package/web/assets/chunk-W44A43WB-lrCpuupA.js +1 -0
- package/web/assets/chunk-ZXARS5L4-CSZRiyOf.js +1 -0
- package/web/assets/classDiagram-KGZ6W3CR-BB-saqC1.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-Bp2bAlS5.js +1 -0
- package/web/assets/cose-bilkent-UX7MHV2Q-BHv2bbtl.js +1 -0
- package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BUxnDPOY.js +43 -0
- package/web/assets/diagram-GF46GFSD-BJTyqqvI.js +24 -0
- package/web/assets/diagram-HNR7UZ2L-fUWreZzx.js +3 -0
- package/web/assets/diagram-QXG6HAR7-DilMHamP.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-8KUrarg1.js +10 -0
- package/web/assets/erDiagram-L5TCEMPS-Doj9mSiW.js +85 -0
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +1 -0
- package/web/assets/{flowDiagram-OTCZ4VVT-aAZw4c_M.js → flowDiagram-H6V6AXG4-BOSR-i3p.js} +12 -12
- package/web/assets/ganttDiagram-JCBTUEKG-BHQssTz6.js +292 -0
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +106 -0
- package/web/assets/index-j4-NuleT.js +623 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Ce_TvtaV.js +2 -0
- package/web/assets/{ishikawaDiagram-YMYX4NHK-BF8AtDaj.js → ishikawaDiagram-BNXS4ZKH-4MXIDCSF.js} +6 -6
- package/web/assets/journeyDiagram-M6C3CM3L-DNPYCpvq.js +139 -0
- package/web/assets/kanban-definition-75IXJCU3-yYdfm8Kk.js +89 -0
- package/web/assets/{katex-GD7MH7QM-CJiOjBBJ.js → katex-K3KEBU37-CrVLz8l7.js} +1 -1
- package/web/assets/mindmap-definition-2TDM6QVE-DFNEKM77.js +96 -0
- package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +1 -0
- package/web/assets/pieDiagram-CU6KROY3-iZAqpvhd.js +30 -0
- package/web/assets/quadrantDiagram-VICAPDV7-bAm6Hi_5.js +7 -0
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +1 -0
- package/web/assets/requirementDiagram-JXO7QTGE-CtDijhnf.js +84 -0
- package/web/assets/sankeyDiagram-URQDO5SZ-LFJz53u5.js +40 -0
- package/web/assets/sequenceDiagram-VS2MUI6T-BdjvyCHM.js +162 -0
- package/web/assets/stateDiagram-7D4R322I-e5odN9fG.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-vPsvjR2D.js +1 -0
- package/web/assets/timeline-definition-O6YCAMPW-DPAksNQp.js +120 -0
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +1 -0
- package/web/assets/vennDiagram-MWXL3ELB-Dtlfdt7J.js +34 -0
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +1 -0
- package/web/assets/wardleyDiagram-CUQ6CDDI-B23uRMUC.js +78 -0
- package/web/assets/{xychartDiagram-ZHJ5623Y-DZ7fP1_3.js → xychartDiagram-N2JHSOCM-DxwHeksW.js} +6 -6
- package/web/index.html +13 -2
- package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BUzkWgDl.js +0 -1
- package/web/assets/architectureDiagram-EMZXCZ2Q-CXbzok1G.js +0 -36
- package/web/assets/blockDiagram-IGV67L2C-DA1QJ4ZB.js +0 -132
- package/web/assets/chunk-3GS5O3IE-B8hpnia8.js +0 -231
- package/web/assets/chunk-3YCYZ6SJ-B-BVu21C.js +0 -1
- package/web/assets/chunk-6NTNNK5N-DW-jYSDr.js +0 -1
- package/web/assets/chunk-A34GCYZU-BbZl-IKy.js +0 -1
- package/web/assets/chunk-DJ7UZH7F-B5tMfF87.js +0 -1
- package/web/assets/chunk-DKKBVRCY-Djm-6K_e.js +0 -4
- package/web/assets/chunk-DU5LTGQ6-QPoynYcp.js +0 -1
- package/web/assets/chunk-FXACKDTF-jieSmbe2.js +0 -159
- package/web/assets/chunk-H3VCZNTA-8EMHZ3SV.js +0 -1
- package/web/assets/chunk-HN6EAY2L-CgE_agsD.js +0 -1
- package/web/assets/chunk-O5ABG6QK-DEZV1O19.js +0 -1
- package/web/assets/chunk-PK6DOVAG-BXv0JnsJ.js +0 -206
- package/web/assets/chunk-RNJOYNJ4-BiBkF9dN.js +0 -1
- package/web/assets/chunk-RWUO3TPN-DTWzAhQ1.js +0 -1
- package/web/assets/chunk-TBF5ZNIQ-BSl6s9lT.js +0 -1
- package/web/assets/chunk-TU3PZOEN-DE5Qhc0N.js +0 -1
- package/web/assets/chunk-TYMNRAUI-D1NDLIMG.js +0 -1
- package/web/assets/chunk-VELTKBKT-C9dVN39o.js +0 -1
- package/web/assets/chunk-W7ZLLLMY-Bu-cdLzs.js +0 -1
- package/web/assets/chunk-WSB5WSVC-Dor71SOz.js +0 -1
- package/web/assets/chunk-XGPFEOL4-CUonLRle.js +0 -1
- package/web/assets/classDiagram-PPOCWD7C-Cdd6UdVv.js +0 -1
- package/web/assets/classDiagram-v2-23LJLIIU-DNhxY2Ib.js +0 -1
- package/web/assets/cose-bilkent-PNC4W37J-DdZq7Qz_.js +0 -1
- package/web/assets/dagre-E77IOHMT-Cfj_6e17.js +0 -4
- package/web/assets/diagram-H7BISOXX-BNvpsrBv.js +0 -43
- package/web/assets/diagram-JC5VWROH-Cn0rtDbJ.js +0 -24
- package/web/assets/diagram-LXUTUG65-CHfoVKNm.js +0 -10
- package/web/assets/diagram-WEHSV5V5-BLxHksnu.js +0 -24
- package/web/assets/erDiagram-GCSMX5X6-DfdN6iqF.js +0 -85
- package/web/assets/ganttDiagram-MUNLMDZQ-BEfC_7Or.js +0 -292
- package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-B6ZeRLP0.js +0 -1
- package/web/assets/gitGraphDiagram-3HKGZ4G3-CG0kC8Q5.js +0 -106
- package/web/assets/index-3NUCUW2s.js +0 -886
- package/web/assets/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +0 -1
- package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +0 -2
- package/web/assets/journeyDiagram-SO5T7YLQ-BW8oKa3N.js +0 -139
- package/web/assets/kanban-definition-LJHFXRCJ-DzbOsR-2.js +0 -89
- package/web/assets/mindmap-definition-2EUWGEK5-BIXGQALq.js +0 -96
- package/web/assets/packet-4T2RLAQJ-EV4IVRXR-Bs7ysNMU.js +0 -1
- package/web/assets/pie-ZZUOXDRM-N23DN5KN-Csi8nnbH.js +0 -1
- package/web/assets/pieDiagram-3IATQBI2-QY-u7P6a.js +0 -30
- package/web/assets/quadrantDiagram-E256RVCF-Di4aNiU8.js +0 -7
- package/web/assets/radar-PYXPWWZC-P6TP7ZYP-DJlyXh2-.js +0 -1
- package/web/assets/requirementDiagram-M5DCFWZL-CzUUrhQD.js +0 -84
- package/web/assets/sankeyDiagram-L3NBLAOT-D2fbMiIU.js +0 -10
- package/web/assets/sequenceDiagram-ZOUHS735-BNdkqguh.js +0 -157
- package/web/assets/stateDiagram-MLPALWAM-51_Q2w2L.js +0 -1
- package/web/assets/stateDiagram-v2-B5LQ5ZB2-8nHs2aNE.js +0 -1
- package/web/assets/timeline-definition-5SPVSISX-DkMiGj4Z.js +0 -120
- package/web/assets/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +0 -1
- package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +0 -1
- package/web/assets/vennDiagram-IE5QUKF5-BCxMmf9q.js +0 -34
- package/web/assets/wardley-RL74JXVD-BCRCBASE-CMStJhpn.js +0 -1
- package/web/assets/wardleyDiagram-XU3VSMPF-ijlLF77s.js +0 -20
- /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
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
-
|
|
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
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
309
|
-
if (
|
|
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
|
]);
|