gitnexus 1.6.5-rc.2 → 1.6.5-rc.21
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/README.md +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/cli/ai-context.d.ts +1 -0
- package/dist/cli/ai-context.js +30 -12
- package/dist/cli/analyze.d.ts +18 -0
- package/dist/cli/analyze.js +33 -4
- package/dist/cli/augment.d.ts +1 -1
- package/dist/cli/augment.js +1 -1
- package/dist/cli/index.js +6 -1
- package/dist/cli/setup.js +6 -0
- package/dist/core/augmentation/engine.d.ts +2 -2
- package/dist/core/augmentation/engine.js +26 -6
- package/dist/core/embeddings/ast-utils.js +2 -1
- package/dist/core/embeddings/http-client.js +22 -6
- package/dist/core/group/extractors/grpc-extractor.js +2 -1
- package/dist/core/group/extractors/http-patterns/python.js +175 -0
- package/dist/core/group/extractors/http-route-extractor.js +2 -1
- package/dist/core/group/extractors/include-extractor.js +2 -1
- package/dist/core/group/extractors/thrift-extractor.js +2 -1
- package/dist/core/group/extractors/tree-sitter-scanner.js +2 -1
- 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.js +166 -47
- package/dist/core/ingestion/community-processor.js +18 -0
- package/dist/core/ingestion/heritage-processor.js +3 -2
- package/dist/core/ingestion/import-processor.js +2 -1
- package/dist/core/ingestion/import-resolvers/standard.d.ts +5 -0
- package/dist/core/ingestion/import-resolvers/standard.js +27 -1
- package/dist/core/ingestion/import-resolvers/utils.js +4 -0
- package/dist/core/ingestion/languages/c/arity-metadata.d.ts +14 -0
- package/dist/core/ingestion/languages/c/arity-metadata.js +94 -0
- package/dist/core/ingestion/languages/c/arity.d.ts +6 -0
- package/dist/core/ingestion/languages/c/arity.js +18 -0
- package/dist/core/ingestion/languages/c/captures.d.ts +2 -0
- package/dist/core/ingestion/languages/c/captures.js +105 -0
- package/dist/core/ingestion/languages/c/header-scan.d.ts +7 -0
- package/dist/core/ingestion/languages/c/header-scan.js +55 -0
- package/dist/core/ingestion/languages/c/import-decomposer.d.ts +8 -0
- package/dist/core/ingestion/languages/c/import-decomposer.js +50 -0
- package/dist/core/ingestion/languages/c/import-target.d.ts +14 -0
- package/dist/core/ingestion/languages/c/import-target.js +57 -0
- package/dist/core/ingestion/languages/c/index.d.ts +11 -0
- package/dist/core/ingestion/languages/c/index.js +11 -0
- package/dist/core/ingestion/languages/c/interpret.d.ts +14 -0
- package/dist/core/ingestion/languages/c/interpret.js +48 -0
- package/dist/core/ingestion/languages/c/merge-bindings.d.ts +7 -0
- package/dist/core/ingestion/languages/c/merge-bindings.js +23 -0
- package/dist/core/ingestion/languages/c/query.d.ts +3 -0
- package/dist/core/ingestion/languages/c/query.js +161 -0
- package/dist/core/ingestion/languages/c/scope-resolver.d.ts +13 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +60 -0
- package/dist/core/ingestion/languages/c/simple-hooks.d.ts +14 -0
- package/dist/core/ingestion/languages/c/simple-hooks.js +19 -0
- package/dist/core/ingestion/languages/c/static-linkage.d.ts +13 -0
- package/dist/core/ingestion/languages/c/static-linkage.js +57 -0
- package/dist/core/ingestion/languages/c-cpp.js +10 -0
- package/dist/core/ingestion/languages/csharp/captures.js +2 -1
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +3 -2
- package/dist/core/ingestion/languages/go/captures.js +2 -1
- package/dist/core/ingestion/languages/go/range-binding.js +2 -1
- 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/languages/python/captures.js +2 -1
- package/dist/core/ingestion/languages/typescript/captures.js +2 -1
- package/dist/core/ingestion/parsing-processor.d.ts +22 -2
- package/dist/core/ingestion/parsing-processor.js +85 -50
- 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-resolution/contract/scope-resolver.d.ts +65 -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 +5 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +25 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +79 -7
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +7 -3
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +24 -4
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +21 -2
- 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 +31 -7
- package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
- package/dist/core/ingestion/tree-sitter-queries.js +10 -0
- package/dist/core/ingestion/workers/parse-worker.js +2 -1
- package/dist/core/lbug/lbug-adapter.d.ts +26 -0
- package/dist/core/lbug/lbug-adapter.js +174 -40
- package/dist/core/lbug/pool-adapter.js +19 -2
- package/dist/core/run-analyze.d.ts +2 -0
- package/dist/core/run-analyze.js +323 -29
- package/dist/core/tree-sitter/safe-parse.d.ts +6 -0
- package/dist/core/tree-sitter/safe-parse.js +32 -0
- package/dist/server/git-clone.js +10 -13
- package/dist/storage/file-hash.d.ts +47 -0
- package/dist/storage/file-hash.js +86 -0
- package/dist/storage/git.d.ts +17 -6
- package/dist/storage/git.js +46 -12
- package/dist/storage/parse-cache.d.ts +67 -0
- package/dist/storage/parse-cache.js +182 -0
- package/dist/storage/repo-manager.d.ts +41 -1
- package/dist/storage/repo-manager.js +17 -2
- package/hooks/claude/gitnexus-hook.cjs +8 -1
- package/hooks/claude/hook-lock.cjs +119 -0
- package/package.json +1 -1
- package/web/assets/{agent-BpHQleHE.js → agent-BG6RCOzz.js} +1 -1
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-F-tujre-.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-2GL7nOvO.js +36 -0
- package/web/assets/blockDiagram-7IZFK4PR-5AjX0pPU.js +132 -0
- package/web/assets/{c4Diagram-DFAF54RM-DeJV1rCn.js → c4Diagram-Y2BXMSZH-hLOeq7xC.js} +2 -2
- package/web/assets/chunk-2T2R6R2M-B_pq_2nf.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CpoohCFN.js +1 -0
- package/web/assets/{chunk-7RZVMHOQ-BdIU-RGO.js → chunk-3SSMPTDK-CfqpR3Nr.js} +1 -1
- package/web/assets/chunk-4R4BOZG6-D3gm7tYj.js +159 -0
- package/web/assets/chunk-6764PJDD-WcI965eO.js +1 -0
- package/web/assets/chunk-AQ6EADP3-BpMj3rQl.js +1 -0
- package/web/assets/{chunk-KSICW3F5-C2tZmXwv.js → chunk-AZZRMDJM-DSoCJlUA.js} +1 -1
- package/web/assets/chunk-C62D2QBJ-CvFF2PnB.js +1 -0
- package/web/assets/chunk-CEXFNPSA-DdNtJtrF.js +1 -0
- package/web/assets/chunk-J5EP6P6S-DtcVaAJI.js +1 -0
- package/web/assets/{chunk-AEOMTBSW-D7qjBMHW.js → chunk-JQRUD6KW-DElaNjc0.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-D0K5or7e.js +1 -0
- package/web/assets/chunk-KRXBNO2N-DpR8iDt8.js +1 -0
- package/web/assets/chunk-LCXTWHL2-DdMObOEk.js +231 -0
- package/web/assets/chunk-LII3EMHJ-I78zXtzi.js +1 -0
- package/web/assets/chunk-RERM46MO-Betu1cSy.js +1 -0
- package/web/assets/chunk-RG4AUYOV-BUCJ2JP5.js +206 -0
- package/web/assets/chunk-RKZBBQEN-Cutpza0t.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-BFUxCvX2.js +1 -0
- package/web/assets/chunk-T5OCTHI4-DKwlkuvB.js +1 -0
- package/web/assets/chunk-UP6H54XL-0YWa0NDg.js +1 -0
- package/web/assets/chunk-UXSXWOXI-CSz0OXpz.js +1 -0
- package/web/assets/chunk-W44A43WB-AOmgoT-X.js +1 -0
- package/web/assets/{chunk-RWUO3TPN-DTWzAhQ1.js → chunk-ZXARS5L4-DIzgxjMw.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-BT-rn7LF.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-uR3nDadY.js +1 -0
- package/web/assets/{cose-bilkent-PNC4W37J-DdZq7Qz_.js → cose-bilkent-UX7MHV2Q-DCSCD1TK.js} +1 -1
- package/web/assets/dagre-ND4H6XIP-CsciHSij.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BKUT5Rpc.js +43 -0
- package/web/assets/diagram-GF46GFSD-Dxb4hZSo.js +24 -0
- package/web/assets/diagram-HNR7UZ2L-D3qus9Cn.js +3 -0
- package/web/assets/diagram-QXG6HAR7-r9BMLGGP.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-BGXqs7-m.js +10 -0
- package/web/assets/{erDiagram-GCSMX5X6-DfdN6iqF.js → erDiagram-L5TCEMPS-LgSWVrkZ.js} +2 -2
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-By7r3bla.js +1 -0
- package/web/assets/flowDiagram-H6V6AXG4-Bj_vV5ky.js +162 -0
- package/web/assets/ganttDiagram-JCBTUEKG-B1eVITSh.js +292 -0
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-ClEP6RdE.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-BP0R-_FD.js +106 -0
- package/web/assets/{index-3NUCUW2s.js → index-oL-ZNYwb.js} +80 -81
- package/web/assets/info-J43DQDTF-KCYPFFUO-bBJRjmP5.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Dmj4OEO3.js +2 -0
- package/web/assets/{ishikawaDiagram-YMYX4NHK-BF8AtDaj.js → ishikawaDiagram-BNXS4ZKH-B3NgQ4lJ.js} +2 -2
- package/web/assets/{journeyDiagram-SO5T7YLQ-BW8oKa3N.js → journeyDiagram-M6C3CM3L-DALmL4_N.js} +3 -3
- package/web/assets/{kanban-definition-LJHFXRCJ-DzbOsR-2.js → kanban-definition-75IXJCU3-AvVbHpnN.js} +4 -4
- package/web/assets/{katex-GD7MH7QM-CJiOjBBJ.js → katex-K3KEBU37-CqF6_ZN-.js} +1 -1
- package/web/assets/{mindmap-definition-2EUWGEK5-BIXGQALq.js → mindmap-definition-2TDM6QVE-B5c9VOzs.js} +28 -28
- package/web/assets/packet-YPE3B663-LP52Z2RK-1ZCldnu3.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-EhjHC5EE.js +1 -0
- package/web/assets/pieDiagram-CU6KROY3-Po2HSSR4.js +30 -0
- package/web/assets/quadrantDiagram-VICAPDV7-C47UxSZD.js +7 -0
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-CvXjgxlW.js +1 -0
- package/web/assets/{requirementDiagram-M5DCFWZL-CzUUrhQD.js → requirementDiagram-JXO7QTGE-CpECN_Hq.js} +6 -6
- package/web/assets/sankeyDiagram-URQDO5SZ-B3b7cLrS.js +40 -0
- package/web/assets/sequenceDiagram-VS2MUI6T-CRJ95oVP.js +162 -0
- package/web/assets/stateDiagram-7D4R322I-C7U9b3ks.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-BQajbtov.js +1 -0
- package/web/assets/{timeline-definition-5SPVSISX-DkMiGj4Z.js → timeline-definition-O6YCAMPW-rtbk6BBo.js} +4 -4
- package/web/assets/treeView-BLDUP644-QA4HXRO3-R2o5gwfP.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-Cesmac_u.js +1 -0
- package/web/assets/{vennDiagram-IE5QUKF5-BCxMmf9q.js → vennDiagram-MWXL3ELB-W8Yoaayh.js} +3 -3
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-B9HYoRgA.js +1 -0
- package/web/assets/wardleyDiagram-CUQ6CDDI-DIZw5Abj.js +78 -0
- package/web/assets/{xychartDiagram-ZHJ5623Y-DZ7fP1_3.js → xychartDiagram-N2JHSOCM-DGRtrj4P.js} +3 -3
- package/web/index.html +2 -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-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/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/flowDiagram-OTCZ4VVT-aAZw4c_M.js +0 -162
- 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/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +0 -1
- package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +0 -2
- 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/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/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +0 -1
- package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +0 -1
- 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-CG-ydtp4.js} +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decompose a PHP `namespace_use_declaration` into one or more
|
|
3
|
+
* `CaptureMatch` objects carrying the synthesized markers
|
|
4
|
+
* `@import.kind` / `@import.source` / `@import.name` / `@import.alias`
|
|
5
|
+
* that `interpretPhpImport` consumes.
|
|
6
|
+
*
|
|
7
|
+
* PHP import forms handled:
|
|
8
|
+
*
|
|
9
|
+
* use Foo\Bar; → namespace, localName=Bar
|
|
10
|
+
* use Foo\Bar as Baz; → alias, localName=Baz
|
|
11
|
+
* use function Foo\bar; → function, localName=bar
|
|
12
|
+
* use const Foo\BAR; → const, localName=BAR
|
|
13
|
+
* use Foo\{A, B as C}; → grouped: one match per clause
|
|
14
|
+
* use function Foo\{f, g as h}; → grouped function variants
|
|
15
|
+
* use const Foo\{X, Y as Z}; → grouped const variants
|
|
16
|
+
*
|
|
17
|
+
* Unlike C#'s decomposer this is 1:N — each grouped use_declaration
|
|
18
|
+
* fans out to one CaptureMatch per inner clause.
|
|
19
|
+
*/
|
|
20
|
+
import type { CaptureMatch } from '../../../../_shared/index.js';
|
|
21
|
+
import { type SyntaxNode } from '../../utils/ast-helpers.js';
|
|
22
|
+
export type PhpImportKind = 'namespace' | 'alias' | 'function' | 'const';
|
|
23
|
+
/**
|
|
24
|
+
* Decompose a `namespace_use_declaration` node into one `CaptureMatch`
|
|
25
|
+
* per logical import. Returns `[]` when the node is unrecognized or
|
|
26
|
+
* carries no resolvable clauses.
|
|
27
|
+
*/
|
|
28
|
+
export declare function splitNamespaceUseDeclaration(stmtNode: SyntaxNode): CaptureMatch[];
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decompose a PHP `namespace_use_declaration` into one or more
|
|
3
|
+
* `CaptureMatch` objects carrying the synthesized markers
|
|
4
|
+
* `@import.kind` / `@import.source` / `@import.name` / `@import.alias`
|
|
5
|
+
* that `interpretPhpImport` consumes.
|
|
6
|
+
*
|
|
7
|
+
* PHP import forms handled:
|
|
8
|
+
*
|
|
9
|
+
* use Foo\Bar; → namespace, localName=Bar
|
|
10
|
+
* use Foo\Bar as Baz; → alias, localName=Baz
|
|
11
|
+
* use function Foo\bar; → function, localName=bar
|
|
12
|
+
* use const Foo\BAR; → const, localName=BAR
|
|
13
|
+
* use Foo\{A, B as C}; → grouped: one match per clause
|
|
14
|
+
* use function Foo\{f, g as h}; → grouped function variants
|
|
15
|
+
* use const Foo\{X, Y as Z}; → grouped const variants
|
|
16
|
+
*
|
|
17
|
+
* Unlike C#'s decomposer this is 1:N — each grouped use_declaration
|
|
18
|
+
* fans out to one CaptureMatch per inner clause.
|
|
19
|
+
*/
|
|
20
|
+
import { nodeToCapture, syntheticCapture } from '../../utils/ast-helpers.js';
|
|
21
|
+
/**
|
|
22
|
+
* Decompose a `namespace_use_declaration` node into one `CaptureMatch`
|
|
23
|
+
* per logical import. Returns `[]` when the node is unrecognized or
|
|
24
|
+
* carries no resolvable clauses.
|
|
25
|
+
*/
|
|
26
|
+
export function splitNamespaceUseDeclaration(stmtNode) {
|
|
27
|
+
if (stmtNode.type !== 'namespace_use_declaration')
|
|
28
|
+
return [];
|
|
29
|
+
// Detect qualifier keyword: `use function` / `use const`
|
|
30
|
+
// tree-sitter-php uses a `use_type` or `function`/`const` keyword
|
|
31
|
+
// child to distinguish them. We scan the raw text before the first
|
|
32
|
+
// backslash-path child.
|
|
33
|
+
const qualifier = detectQualifier(stmtNode);
|
|
34
|
+
// Grouped use: `use Foo\{A, B as C}` — find namespace_use_group child.
|
|
35
|
+
const groupNode = findNamedChild(stmtNode, 'namespace_use_group');
|
|
36
|
+
if (groupNode !== null) {
|
|
37
|
+
return decomposeGrouped(stmtNode, groupNode, qualifier);
|
|
38
|
+
}
|
|
39
|
+
// Single use clause (possibly aliased).
|
|
40
|
+
const spec = parseSingleUseClause(stmtNode, qualifier);
|
|
41
|
+
if (spec === null)
|
|
42
|
+
return [];
|
|
43
|
+
return [buildImportMatch(stmtNode, spec)];
|
|
44
|
+
}
|
|
45
|
+
// ── Qualifier detection ────────────────────────────────────────────────────
|
|
46
|
+
/**
|
|
47
|
+
* Return the qualifier keyword appearing after `use`:
|
|
48
|
+
* `'function'`, `'const'`, or `null` for plain namespace use.
|
|
49
|
+
*
|
|
50
|
+
* tree-sitter-php emits the qualifier as a `name` node with text
|
|
51
|
+
* "function" or "const" (not a keyword token in recent grammars),
|
|
52
|
+
* or as a dedicated `use_type` node. We inspect the node's raw text
|
|
53
|
+
* to be grammar-version-agnostic.
|
|
54
|
+
*/
|
|
55
|
+
function detectQualifier(node) {
|
|
56
|
+
const raw = node.text;
|
|
57
|
+
// Match `use function` or `use const` at the start (after optional whitespace)
|
|
58
|
+
if (/^\s*use\s+function\s/i.test(raw))
|
|
59
|
+
return 'function';
|
|
60
|
+
if (/^\s*use\s+const\s/i.test(raw))
|
|
61
|
+
return 'const';
|
|
62
|
+
return 'namespace';
|
|
63
|
+
}
|
|
64
|
+
// ── Single clause parsing ──────────────────────────────────────────────────
|
|
65
|
+
function parseSingleUseClause(node, qualifier) {
|
|
66
|
+
// A plain `namespace_use_declaration` has one or more
|
|
67
|
+
// `namespace_use_clause` named children (each clause is one import,
|
|
68
|
+
// comma-separated for multiple). For the single case there is one.
|
|
69
|
+
const clause = findNamedChild(node, 'namespace_use_clause');
|
|
70
|
+
if (clause !== null)
|
|
71
|
+
return parseUseClause(clause, qualifier);
|
|
72
|
+
// Older grammar versions may put the qualified_name directly under
|
|
73
|
+
// the declaration node. Check for a qualified_name or name child.
|
|
74
|
+
const qualName = findNamedChild(node, 'qualified_name') ?? findNamedChild(node, 'name');
|
|
75
|
+
if (qualName === null)
|
|
76
|
+
return null;
|
|
77
|
+
const source = qualName.text.trim();
|
|
78
|
+
if (source === '')
|
|
79
|
+
return null;
|
|
80
|
+
return {
|
|
81
|
+
kind: qualifier,
|
|
82
|
+
source,
|
|
83
|
+
name: lastSegment(source),
|
|
84
|
+
atNode: node,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function parseUseClause(clause, qualifier) {
|
|
88
|
+
// namespace_use_clause:
|
|
89
|
+
// qualified_name (or name)
|
|
90
|
+
// optional: alias_clause → "as" name (some grammar versions)
|
|
91
|
+
// optional: bare name node (tree-sitter-php ≥ 0.22 emits the
|
|
92
|
+
// alias as a sibling `name` node
|
|
93
|
+
// directly, not inside alias_clause)
|
|
94
|
+
const qualName = findNamedChild(clause, 'qualified_name') ?? findNamedChild(clause, 'name');
|
|
95
|
+
if (qualName === null)
|
|
96
|
+
return null;
|
|
97
|
+
const source = qualName.text.trim();
|
|
98
|
+
if (source === '')
|
|
99
|
+
return null;
|
|
100
|
+
// Strategy 1: explicit alias_clause wrapper (older grammar versions).
|
|
101
|
+
const aliasClause = findNamedChild(clause, 'alias_clause');
|
|
102
|
+
if (aliasClause !== null) {
|
|
103
|
+
// alias_clause: "as" name
|
|
104
|
+
const aliasName = findNamedChild(aliasClause, 'name') ?? aliasClause.firstNamedChild;
|
|
105
|
+
const alias = aliasName?.text.trim() ?? '';
|
|
106
|
+
if (alias === '')
|
|
107
|
+
return null;
|
|
108
|
+
return {
|
|
109
|
+
kind: 'alias',
|
|
110
|
+
source,
|
|
111
|
+
name: alias,
|
|
112
|
+
alias,
|
|
113
|
+
atNode: clause,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Strategy 2: bare sibling `name` node after the qualified_name.
|
|
117
|
+
// tree-sitter-php (≥ 0.22) emits `use Foo\Bar as Baz` as:
|
|
118
|
+
// namespace_use_clause
|
|
119
|
+
// qualified_name "Foo\Bar"
|
|
120
|
+
// name "Baz" ← alias, no alias_clause wrapper
|
|
121
|
+
// Detect by: clause has ≥2 named children AND the last named child is
|
|
122
|
+
// a `name` node that differs from the qualName node.
|
|
123
|
+
if (clause.namedChildCount >= 2) {
|
|
124
|
+
const lastChild = clause.namedChild(clause.namedChildCount - 1);
|
|
125
|
+
if (lastChild !== null && lastChild !== qualName && lastChild.type === 'name') {
|
|
126
|
+
const alias = lastChild.text.trim();
|
|
127
|
+
if (alias !== '') {
|
|
128
|
+
return {
|
|
129
|
+
kind: 'alias',
|
|
130
|
+
source,
|
|
131
|
+
name: alias,
|
|
132
|
+
alias,
|
|
133
|
+
atNode: clause,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
kind: qualifier,
|
|
140
|
+
source,
|
|
141
|
+
name: lastSegment(source),
|
|
142
|
+
atNode: clause,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ── Grouped use decomposition ──────────────────────────────────────────────
|
|
146
|
+
/**
|
|
147
|
+
* Decompose `use Foo\Bar\{A, B as C, function f, const X}` into one
|
|
148
|
+
* `CaptureMatch` per inner clause.
|
|
149
|
+
*
|
|
150
|
+
* The leading prefix (`Foo\Bar`) is prepended to each inner path.
|
|
151
|
+
* Inner clauses can override the qualifier with their own `function` /
|
|
152
|
+
* `const` keyword inside the group.
|
|
153
|
+
*/
|
|
154
|
+
function decomposeGrouped(stmtNode, groupNode, outerQualifier) {
|
|
155
|
+
// The prefix is the qualified_name that precedes the `{...}` group.
|
|
156
|
+
const prefixNode = findNamedChild(stmtNode, 'qualified_name') ?? findNamedChild(stmtNode, 'name');
|
|
157
|
+
const prefix = prefixNode?.text.trim() ?? '';
|
|
158
|
+
const out = [];
|
|
159
|
+
for (let i = 0; i < groupNode.namedChildCount; i++) {
|
|
160
|
+
const child = groupNode.namedChild(i);
|
|
161
|
+
if (child === null)
|
|
162
|
+
continue;
|
|
163
|
+
// Each child in a group may be:
|
|
164
|
+
// namespace_use_clause — plain or aliased
|
|
165
|
+
// namespace_use_type — `function` or `const` qualifier inside group
|
|
166
|
+
// We detect an inline qualifier by checking the raw text of the clause.
|
|
167
|
+
if (child.type !== 'namespace_use_clause')
|
|
168
|
+
continue;
|
|
169
|
+
const innerQualifier = detectInnerQualifier(child) ?? outerQualifier;
|
|
170
|
+
const spec = parseInnerClause(child, prefix, innerQualifier);
|
|
171
|
+
if (spec !== null) {
|
|
172
|
+
out.push(buildImportMatch(stmtNode, spec));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Detect an inline qualifier keyword inside a grouped clause.
|
|
179
|
+
* e.g. `use Foo\{function bar, const BAZ}` — each clause may start with
|
|
180
|
+
* `function` or `const`.
|
|
181
|
+
*/
|
|
182
|
+
function detectInnerQualifier(clause) {
|
|
183
|
+
const raw = clause.text.trim();
|
|
184
|
+
if (/^function\s/i.test(raw))
|
|
185
|
+
return 'function';
|
|
186
|
+
if (/^const\s/i.test(raw))
|
|
187
|
+
return 'const';
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
function parseInnerClause(clause, prefix, qualifier) {
|
|
191
|
+
const qualName = findNamedChild(clause, 'qualified_name') ?? findNamedChild(clause, 'name');
|
|
192
|
+
if (qualName === null)
|
|
193
|
+
return null;
|
|
194
|
+
// Strip inline `function` / `const` text prefix if present in the text.
|
|
195
|
+
let innerPath = qualName.text.trim();
|
|
196
|
+
innerPath = innerPath.replace(/^(?:function|const)\s+/i, '').trim();
|
|
197
|
+
if (innerPath === '')
|
|
198
|
+
return null;
|
|
199
|
+
const source = prefix !== '' ? `${prefix}\\${innerPath}` : innerPath;
|
|
200
|
+
// Strategy 1: explicit alias_clause wrapper (older grammar versions).
|
|
201
|
+
const aliasClause = findNamedChild(clause, 'alias_clause');
|
|
202
|
+
if (aliasClause !== null) {
|
|
203
|
+
const aliasName = findNamedChild(aliasClause, 'name') ?? aliasClause.firstNamedChild;
|
|
204
|
+
const alias = aliasName?.text.trim() ?? '';
|
|
205
|
+
if (alias === '')
|
|
206
|
+
return null;
|
|
207
|
+
return {
|
|
208
|
+
kind: 'alias',
|
|
209
|
+
source,
|
|
210
|
+
name: alias,
|
|
211
|
+
alias,
|
|
212
|
+
atNode: clause,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
// Strategy 2: bare sibling `name` node after the qualified_name (tree-sitter-php ≥ 0.22).
|
|
216
|
+
if (clause.namedChildCount >= 2) {
|
|
217
|
+
const lastChild = clause.namedChild(clause.namedChildCount - 1);
|
|
218
|
+
if (lastChild !== null && lastChild !== qualName && lastChild.type === 'name') {
|
|
219
|
+
const alias = lastChild.text.trim();
|
|
220
|
+
if (alias !== '') {
|
|
221
|
+
return {
|
|
222
|
+
kind: 'alias',
|
|
223
|
+
source,
|
|
224
|
+
name: alias,
|
|
225
|
+
alias,
|
|
226
|
+
atNode: clause,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
kind: qualifier,
|
|
233
|
+
source,
|
|
234
|
+
name: lastSegment(innerPath),
|
|
235
|
+
atNode: clause,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
// ── CaptureMatch builder ───────────────────────────────────────────────────
|
|
239
|
+
function buildImportMatch(stmtNode, spec) {
|
|
240
|
+
const m = {
|
|
241
|
+
'@import.statement': nodeToCapture('@import.statement', stmtNode),
|
|
242
|
+
'@import.kind': syntheticCapture('@import.kind', spec.atNode, spec.kind),
|
|
243
|
+
'@import.source': syntheticCapture('@import.source', spec.atNode, spec.source),
|
|
244
|
+
'@import.name': syntheticCapture('@import.name', spec.atNode, spec.name),
|
|
245
|
+
};
|
|
246
|
+
if (spec.alias !== undefined) {
|
|
247
|
+
m['@import.alias'] = syntheticCapture('@import.alias', spec.atNode, spec.alias);
|
|
248
|
+
}
|
|
249
|
+
return m;
|
|
250
|
+
}
|
|
251
|
+
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
252
|
+
/** Last backslash-separated segment: `Foo\Bar\Baz` → `Baz`. */
|
|
253
|
+
function lastSegment(path) {
|
|
254
|
+
const parts = path.split('\\').filter(Boolean);
|
|
255
|
+
return parts[parts.length - 1] ?? path;
|
|
256
|
+
}
|
|
257
|
+
/** Find the first named child with a given node type. */
|
|
258
|
+
function findNamedChild(node, type) {
|
|
259
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
260
|
+
const child = node.namedChild(i);
|
|
261
|
+
if (child !== null && child.type === type)
|
|
262
|
+
return child;
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter from `(ParsedImport, WorkspaceIndex)` → concrete file path.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to the existing `resolvePhpImportInternal` (PSR-4 via
|
|
5
|
+
* composer.json + suffix matching fallback). The `WorkspaceIndex` is
|
|
6
|
+
* opaque at this layer; consumers wire a `PhpResolveContext` shape
|
|
7
|
+
* carrying `fromFile` + `allFilePaths`.
|
|
8
|
+
*
|
|
9
|
+
* `loadPhpComposerConfig` is the `ScopeResolver.loadResolutionConfig`
|
|
10
|
+
* implementation — it loads `composer.json` once per workspace pass and
|
|
11
|
+
* threads the parsed config into every subsequent `resolveImportTarget`
|
|
12
|
+
* call via the opaque `resolutionConfig` parameter.
|
|
13
|
+
*
|
|
14
|
+
* Returning `null` lets the finalize algorithm mark the edge as
|
|
15
|
+
* `linkStatus: 'unresolved'`.
|
|
16
|
+
*/
|
|
17
|
+
import type { ParsedImport, WorkspaceIndex } from '../../../../_shared/index.js';
|
|
18
|
+
import type { ComposerConfig } from '../../language-config.js';
|
|
19
|
+
export interface PhpResolveContext {
|
|
20
|
+
readonly fromFile: string;
|
|
21
|
+
readonly allFilePaths: ReadonlySet<string>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Load and parse `composer.json` from the repo root. Returns a
|
|
25
|
+
* `ComposerConfig` object (PSR-4 namespace → directory mappings) or
|
|
26
|
+
* `null` when no `composer.json` is present or it cannot be parsed.
|
|
27
|
+
*
|
|
28
|
+
* The result is threaded into each `resolvePhpImportInternal` call as
|
|
29
|
+
* the `composerConfig` argument.
|
|
30
|
+
*/
|
|
31
|
+
export declare function loadPhpComposerConfig(repoPath: string): ComposerConfig | null;
|
|
32
|
+
/**
|
|
33
|
+
* LanguageProvider-shaped adapter: `(ParsedImport, WorkspaceIndex) → string | null`.
|
|
34
|
+
*
|
|
35
|
+
* The `WorkspaceIndex` is `unknown` in the shared contract. The scope-resolution
|
|
36
|
+
* orchestrator hands us a `PhpResolveContext`-shaped object; narrow structurally
|
|
37
|
+
* rather than via a cast chain so unexpected shapes return `null` cleanly.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolvePhpImportTarget(parsedImport: ParsedImport, workspaceIndex: WorkspaceIndex): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* ScopeResolver-shaped adapter: `(targetRaw, fromFile, allFilePaths, resolutionConfig?) → string | null`.
|
|
42
|
+
*
|
|
43
|
+
* Used inside `scope-resolver.ts`. Accepts the optional `resolutionConfig`
|
|
44
|
+
* (a `ComposerConfig | null` loaded once per workspace by
|
|
45
|
+
* `loadPhpComposerConfig`) and threads it into `resolvePhpImportInternal`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolvePhpImportTargetInternal(targetRaw: string, _fromFile: string, allFilePaths: ReadonlySet<string>, resolutionConfig?: unknown): string | null;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter from `(ParsedImport, WorkspaceIndex)` → concrete file path.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to the existing `resolvePhpImportInternal` (PSR-4 via
|
|
5
|
+
* composer.json + suffix matching fallback). The `WorkspaceIndex` is
|
|
6
|
+
* opaque at this layer; consumers wire a `PhpResolveContext` shape
|
|
7
|
+
* carrying `fromFile` + `allFilePaths`.
|
|
8
|
+
*
|
|
9
|
+
* `loadPhpComposerConfig` is the `ScopeResolver.loadResolutionConfig`
|
|
10
|
+
* implementation — it loads `composer.json` once per workspace pass and
|
|
11
|
+
* threads the parsed config into every subsequent `resolveImportTarget`
|
|
12
|
+
* call via the opaque `resolutionConfig` parameter.
|
|
13
|
+
*
|
|
14
|
+
* Returning `null` lets the finalize algorithm mark the edge as
|
|
15
|
+
* `linkStatus: 'unresolved'`.
|
|
16
|
+
*/
|
|
17
|
+
import { resolvePhpImportInternal } from '../../import-resolvers/php.js';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
// ─── loadResolutionConfig ──────────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Load and parse `composer.json` from the repo root. Returns a
|
|
23
|
+
* `ComposerConfig` object (PSR-4 namespace → directory mappings) or
|
|
24
|
+
* `null` when no `composer.json` is present or it cannot be parsed.
|
|
25
|
+
*
|
|
26
|
+
* The result is threaded into each `resolvePhpImportInternal` call as
|
|
27
|
+
* the `composerConfig` argument.
|
|
28
|
+
*/
|
|
29
|
+
export function loadPhpComposerConfig(repoPath) {
|
|
30
|
+
try {
|
|
31
|
+
const composerPath = join(repoPath, 'composer.json');
|
|
32
|
+
const raw = readFileSync(composerPath, 'utf8');
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
35
|
+
return null;
|
|
36
|
+
const composer = parsed;
|
|
37
|
+
const autoload = composer['autoload'];
|
|
38
|
+
if (autoload === undefined)
|
|
39
|
+
return null;
|
|
40
|
+
const psr4Raw = (autoload['psr-4'] ?? {});
|
|
41
|
+
const psr4 = new Map();
|
|
42
|
+
for (const [ns, dirs] of Object.entries(psr4Raw)) {
|
|
43
|
+
// namespace prefix ends with `\` — keep as-is; resolver strips it
|
|
44
|
+
const normalizedNs = ns.replace(/\\$/, '');
|
|
45
|
+
const dir = Array.isArray(dirs) ? dirs[0] : dirs;
|
|
46
|
+
if (typeof dir === 'string') {
|
|
47
|
+
// Normalize directory path (strip trailing slash)
|
|
48
|
+
const normalizedDir = dir.replace(/\/+$/, '');
|
|
49
|
+
psr4.set(normalizedNs, normalizedDir);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { psr4 };
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ─── resolvePhpImportTarget ────────────────────────────────────────────────
|
|
59
|
+
/**
|
|
60
|
+
* LanguageProvider-shaped adapter: `(ParsedImport, WorkspaceIndex) → string | null`.
|
|
61
|
+
*
|
|
62
|
+
* The `WorkspaceIndex` is `unknown` in the shared contract. The scope-resolution
|
|
63
|
+
* orchestrator hands us a `PhpResolveContext`-shaped object; narrow structurally
|
|
64
|
+
* rather than via a cast chain so unexpected shapes return `null` cleanly.
|
|
65
|
+
*/
|
|
66
|
+
export function resolvePhpImportTarget(parsedImport, workspaceIndex) {
|
|
67
|
+
const ctx = workspaceIndex;
|
|
68
|
+
if (ctx === undefined ||
|
|
69
|
+
typeof ctx.fromFile !== 'string' ||
|
|
70
|
+
!(ctx.allFilePaths instanceof Set)) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (parsedImport.kind === 'dynamic-unresolved')
|
|
74
|
+
return null;
|
|
75
|
+
if (parsedImport.targetRaw === null || parsedImport.targetRaw === '')
|
|
76
|
+
return null;
|
|
77
|
+
const allFiles = ctx.allFilePaths;
|
|
78
|
+
const normalizedFileList = [...allFiles].map((f) => f.replace(/\\/g, '/'));
|
|
79
|
+
const allFileList = [...allFiles];
|
|
80
|
+
return resolvePhpImportInternal(parsedImport.targetRaw, null, // composerConfig not available through LanguageProvider path
|
|
81
|
+
allFiles, normalizedFileList, allFileList, undefined);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* ScopeResolver-shaped adapter: `(targetRaw, fromFile, allFilePaths, resolutionConfig?) → string | null`.
|
|
85
|
+
*
|
|
86
|
+
* Used inside `scope-resolver.ts`. Accepts the optional `resolutionConfig`
|
|
87
|
+
* (a `ComposerConfig | null` loaded once per workspace by
|
|
88
|
+
* `loadPhpComposerConfig`) and threads it into `resolvePhpImportInternal`.
|
|
89
|
+
*/
|
|
90
|
+
export function resolvePhpImportTargetInternal(targetRaw, _fromFile, allFilePaths, resolutionConfig) {
|
|
91
|
+
if (targetRaw === '')
|
|
92
|
+
return null;
|
|
93
|
+
const composerConfig = resolutionConfig !== undefined && resolutionConfig !== null
|
|
94
|
+
? resolutionConfig
|
|
95
|
+
: null;
|
|
96
|
+
const allFiles = allFilePaths;
|
|
97
|
+
const normalizedFileList = [...allFiles].map((f) => f.replace(/\\/g, '/'));
|
|
98
|
+
const allFileList = [...allFiles];
|
|
99
|
+
return resolvePhpImportInternal(targetRaw, composerConfig, allFiles, normalizedFileList, allFileList, undefined);
|
|
100
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP scope-resolution hooks (RFC #909 Ring 3 LANG-php, #938).
|
|
3
|
+
*
|
|
4
|
+
* Public API barrel. Consumers should import from this file rather than
|
|
5
|
+
* the individual modules.
|
|
6
|
+
*
|
|
7
|
+
* Module layout (each file is a single concern):
|
|
8
|
+
*
|
|
9
|
+
* - `query.ts` — tree-sitter query + lazy parser/query singletons
|
|
10
|
+
* - `captures.ts` — `emitPhpScopeCaptures` orchestrator
|
|
11
|
+
* - `import-decomposer.ts` — each `namespace_use_declaration` → ParsedImport captures
|
|
12
|
+
* - `interpret.ts` — capture-match → `ParsedImport` / `ParsedTypeBinding`
|
|
13
|
+
* - `simple-hooks.ts` — small/no-op hooks made explicit
|
|
14
|
+
* - `receiver-binding.ts` — synthesize `$this` / `parent` type-bindings on
|
|
15
|
+
* instance-method entry
|
|
16
|
+
* - `merge-bindings.ts` — PHP `use` precedence (local > import > wildcard)
|
|
17
|
+
* - `arity.ts` — PHP arity compatibility (variadic, defaults)
|
|
18
|
+
* - `arity-metadata.ts` — synthesize arity metadata from declarations
|
|
19
|
+
* - `import-target.ts` — `(ParsedImport, WorkspaceIndex) → file path` adapter
|
|
20
|
+
* wrapping `resolvePhpImportInternal` (PSR-4 + composer.json)
|
|
21
|
+
* - `scope-resolver.ts` — `ScopeResolver` registered in `SCOPE_RESOLVERS`
|
|
22
|
+
* - `cache-stats.ts` — PROF_SCOPE_RESOLUTION cache hit/miss counters
|
|
23
|
+
*
|
|
24
|
+
* ## Known limitations
|
|
25
|
+
*
|
|
26
|
+
* The PHP registry-primary path intentionally does NOT resolve the following.
|
|
27
|
+
* Each is a conscious trade-off at migration time.
|
|
28
|
+
*
|
|
29
|
+
* 1. **Trait `$this` → using-class binding** — for methods defined in a
|
|
30
|
+
* trait, `$this` is synthesized as a binding to the trait itself.
|
|
31
|
+
* Resolving `$this` to the actual using-class type requires cross-file
|
|
32
|
+
* analysis of all `use TraitName;` declarations in class bodies.
|
|
33
|
+
* Deferred to a follow-up; trait method resolution falls back to the
|
|
34
|
+
* trait scope.
|
|
35
|
+
*
|
|
36
|
+
* 2. **Anonymous classes** — `new class extends Foo { }` have no stable
|
|
37
|
+
* class name and are skipped by receiver-binding synthesis. The class
|
|
38
|
+
* body is still scoped; member lookups inside it will fall back to
|
|
39
|
+
* free-call resolution.
|
|
40
|
+
*
|
|
41
|
+
* 3. **Dynamic property/method access** — `$obj->{$name}()` and
|
|
42
|
+
* `$$varName` are not followed. The dynamic receiver is ignored and
|
|
43
|
+
* the call falls through to the shared free-call resolver.
|
|
44
|
+
*
|
|
45
|
+
* 4. **Magic methods** — `__get`, `__set`, `__call`, `__callStatic` are
|
|
46
|
+
* not modeled as virtual dispatch; they appear as regular method
|
|
47
|
+
* declarations in the graph but calls that would route through them
|
|
48
|
+
* at runtime are not distinguished.
|
|
49
|
+
*
|
|
50
|
+
* 5. **Laravel facade magic** — `App::make(...)`, `Cache::get(...)` etc.
|
|
51
|
+
* resolve statically to the Facade class rather than the underlying
|
|
52
|
+
* bound implementation. Deferred to a Laravel-specific plugin.
|
|
53
|
+
*
|
|
54
|
+
* 6. **Intersection types in parameters** — `T&U $param` takes the first
|
|
55
|
+
* named part (`T`). This matches the legacy type-extractor's behavior.
|
|
56
|
+
*
|
|
57
|
+
* Shadow-harness corpus parity is the authoritative signal for which of
|
|
58
|
+
* these matter in practice. The CI parity gate blocks any PR that regresses
|
|
59
|
+
* either the legacy or registry-primary run of
|
|
60
|
+
* `test/integration/resolvers/php.test.ts`.
|
|
61
|
+
*/
|
|
62
|
+
export { emitPhpScopeCaptures } from './captures.js';
|
|
63
|
+
export { getPhpCaptureCacheStats, resetPhpCaptureCacheStats } from './cache-stats.js';
|
|
64
|
+
export { interpretPhpImport, interpretPhpTypeBinding } from './interpret.js';
|
|
65
|
+
export { phpMergeBindings } from './merge-bindings.js';
|
|
66
|
+
export { phpArityCompatibility } from './arity.js';
|
|
67
|
+
export { resolvePhpImportTarget, type PhpResolveContext } from './import-target.js';
|
|
68
|
+
export { phpBindingScopeFor, phpImportOwningScope, phpReceiverBinding } from './simple-hooks.js';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP scope-resolution hooks (RFC #909 Ring 3 LANG-php, #938).
|
|
3
|
+
*
|
|
4
|
+
* Public API barrel. Consumers should import from this file rather than
|
|
5
|
+
* the individual modules.
|
|
6
|
+
*
|
|
7
|
+
* Module layout (each file is a single concern):
|
|
8
|
+
*
|
|
9
|
+
* - `query.ts` — tree-sitter query + lazy parser/query singletons
|
|
10
|
+
* - `captures.ts` — `emitPhpScopeCaptures` orchestrator
|
|
11
|
+
* - `import-decomposer.ts` — each `namespace_use_declaration` → ParsedImport captures
|
|
12
|
+
* - `interpret.ts` — capture-match → `ParsedImport` / `ParsedTypeBinding`
|
|
13
|
+
* - `simple-hooks.ts` — small/no-op hooks made explicit
|
|
14
|
+
* - `receiver-binding.ts` — synthesize `$this` / `parent` type-bindings on
|
|
15
|
+
* instance-method entry
|
|
16
|
+
* - `merge-bindings.ts` — PHP `use` precedence (local > import > wildcard)
|
|
17
|
+
* - `arity.ts` — PHP arity compatibility (variadic, defaults)
|
|
18
|
+
* - `arity-metadata.ts` — synthesize arity metadata from declarations
|
|
19
|
+
* - `import-target.ts` — `(ParsedImport, WorkspaceIndex) → file path` adapter
|
|
20
|
+
* wrapping `resolvePhpImportInternal` (PSR-4 + composer.json)
|
|
21
|
+
* - `scope-resolver.ts` — `ScopeResolver` registered in `SCOPE_RESOLVERS`
|
|
22
|
+
* - `cache-stats.ts` — PROF_SCOPE_RESOLUTION cache hit/miss counters
|
|
23
|
+
*
|
|
24
|
+
* ## Known limitations
|
|
25
|
+
*
|
|
26
|
+
* The PHP registry-primary path intentionally does NOT resolve the following.
|
|
27
|
+
* Each is a conscious trade-off at migration time.
|
|
28
|
+
*
|
|
29
|
+
* 1. **Trait `$this` → using-class binding** — for methods defined in a
|
|
30
|
+
* trait, `$this` is synthesized as a binding to the trait itself.
|
|
31
|
+
* Resolving `$this` to the actual using-class type requires cross-file
|
|
32
|
+
* analysis of all `use TraitName;` declarations in class bodies.
|
|
33
|
+
* Deferred to a follow-up; trait method resolution falls back to the
|
|
34
|
+
* trait scope.
|
|
35
|
+
*
|
|
36
|
+
* 2. **Anonymous classes** — `new class extends Foo { }` have no stable
|
|
37
|
+
* class name and are skipped by receiver-binding synthesis. The class
|
|
38
|
+
* body is still scoped; member lookups inside it will fall back to
|
|
39
|
+
* free-call resolution.
|
|
40
|
+
*
|
|
41
|
+
* 3. **Dynamic property/method access** — `$obj->{$name}()` and
|
|
42
|
+
* `$$varName` are not followed. The dynamic receiver is ignored and
|
|
43
|
+
* the call falls through to the shared free-call resolver.
|
|
44
|
+
*
|
|
45
|
+
* 4. **Magic methods** — `__get`, `__set`, `__call`, `__callStatic` are
|
|
46
|
+
* not modeled as virtual dispatch; they appear as regular method
|
|
47
|
+
* declarations in the graph but calls that would route through them
|
|
48
|
+
* at runtime are not distinguished.
|
|
49
|
+
*
|
|
50
|
+
* 5. **Laravel facade magic** — `App::make(...)`, `Cache::get(...)` etc.
|
|
51
|
+
* resolve statically to the Facade class rather than the underlying
|
|
52
|
+
* bound implementation. Deferred to a Laravel-specific plugin.
|
|
53
|
+
*
|
|
54
|
+
* 6. **Intersection types in parameters** — `T&U $param` takes the first
|
|
55
|
+
* named part (`T`). This matches the legacy type-extractor's behavior.
|
|
56
|
+
*
|
|
57
|
+
* Shadow-harness corpus parity is the authoritative signal for which of
|
|
58
|
+
* these matter in practice. The CI parity gate blocks any PR that regresses
|
|
59
|
+
* either the legacy or registry-primary run of
|
|
60
|
+
* `test/integration/resolvers/php.test.ts`.
|
|
61
|
+
*/
|
|
62
|
+
export { emitPhpScopeCaptures } from './captures.js';
|
|
63
|
+
export { getPhpCaptureCacheStats, resetPhpCaptureCacheStats } from './cache-stats.js';
|
|
64
|
+
export { interpretPhpImport, interpretPhpTypeBinding } from './interpret.js';
|
|
65
|
+
export { phpMergeBindings } from './merge-bindings.js';
|
|
66
|
+
export { phpArityCompatibility } from './arity.js';
|
|
67
|
+
export { resolvePhpImportTarget } from './import-target.js';
|
|
68
|
+
export { phpBindingScopeFor, phpImportOwningScope, phpReceiverBinding } from './simple-hooks.js';
|
|
69
|
+
// NOTE: phpScopeResolver is intentionally NOT re-exported from this barrel.
|
|
70
|
+
// Importing it here would create a circular dependency:
|
|
71
|
+
// php.ts → php/index.js → php/scope-resolver.js → ../php.js
|
|
72
|
+
// Registry and other consumers must import directly from './php/scope-resolver.js'.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture-match → semantic-shape interpreters for PHP.
|
|
3
|
+
*
|
|
4
|
+
* - `interpretPhpImport` → `ParsedImport`
|
|
5
|
+
* - `interpretPhpTypeBinding` → `ParsedTypeBinding`
|
|
6
|
+
*
|
|
7
|
+
* Import matches arrive pre-decomposed by `emitPhpScopeCaptures` (one
|
|
8
|
+
* CaptureMatch per logical import, with synthesized `@import.kind /
|
|
9
|
+
* source / name / alias` markers). Type-binding matches arrive from
|
|
10
|
+
* the raw query captures — each `@type-binding.*` anchor carries
|
|
11
|
+
* `@type-binding.name` + `@type-binding.type`.
|
|
12
|
+
*/
|
|
13
|
+
import type { CaptureMatch, ParsedImport, ParsedTypeBinding } from '../../../../_shared/index.js';
|
|
14
|
+
export declare function interpretPhpImport(captures: CaptureMatch): ParsedImport | null;
|
|
15
|
+
export declare function interpretPhpTypeBinding(captures: CaptureMatch): ParsedTypeBinding | null;
|
|
16
|
+
/**
|
|
17
|
+
* Normalize a PHP type string to a simple class identifier, or `null`
|
|
18
|
+
* when the type is uninformative (primitive, void, mixed, self, etc.).
|
|
19
|
+
*
|
|
20
|
+
* Rules applied in order:
|
|
21
|
+
* 1. Strip nullable prefix `?`
|
|
22
|
+
* 2. Split on `|` (union) — keep only if exactly one non-null part
|
|
23
|
+
* 3. Take first part of `&` intersection
|
|
24
|
+
* 4. Strip array suffix `[]`
|
|
25
|
+
* 5. Strip generic wrapper `Collection<User>` → `User`
|
|
26
|
+
* 6. Canonicalize leading backslash off: `\App\Models\User` → `App\Models\User`
|
|
27
|
+
* 7. Reject PHP primitive / pseudo types
|
|
28
|
+
*
|
|
29
|
+
* The qualified form is preserved on `TypeRef.rawName` so downstream PHP
|
|
30
|
+
* receiver resolution can distinguish `\App\Other\User` from a same-simple-name
|
|
31
|
+
* `User` reachable via `use`. Without this, fully-qualified type hints collapse
|
|
32
|
+
* to ambiguous simple names and resolve against the caller's scope chain
|
|
33
|
+
* instead of the explicit target the source named (Codex PR #1497 review,
|
|
34
|
+
* finding 1).
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizePhpType(raw: string): string | null;
|