gitnexus 1.6.4-rc.2 → 1.6.4-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.
Files changed (243) hide show
  1. package/README.md +35 -0
  2. package/dist/_shared/index.d.ts +1 -1
  3. package/dist/_shared/index.d.ts.map +1 -1
  4. package/dist/_shared/index.js +1 -1
  5. package/dist/_shared/index.js.map +1 -1
  6. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +22 -14
  7. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
  8. package/dist/_shared/scope-resolution/finalize-algorithm.js +298 -37
  9. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  10. package/dist/_shared/scope-resolution/scope-tree.d.ts +23 -1
  11. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  12. package/dist/_shared/scope-resolution/scope-tree.js +36 -2
  13. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  14. package/dist/_shared/scope-resolution/types.d.ts +47 -3
  15. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  16. package/dist/_shared/scope-resolution/types.js +10 -2
  17. package/dist/_shared/scope-resolution/types.js.map +1 -1
  18. package/dist/cli/analyze.d.ts +6 -0
  19. package/dist/cli/analyze.js +35 -0
  20. package/dist/cli/doctor.d.ts +1 -0
  21. package/dist/cli/doctor.js +31 -0
  22. package/dist/cli/index.js +13 -0
  23. package/dist/cli/setup.js +2 -2
  24. package/dist/core/embeddings/config.d.ts +2 -0
  25. package/dist/core/embeddings/config.js +36 -0
  26. package/dist/core/embeddings/embedder.js +11 -6
  27. package/dist/core/embeddings/embedding-pipeline.d.ts +7 -1
  28. package/dist/core/embeddings/embedding-pipeline.js +93 -29
  29. package/dist/core/embeddings/exact-search.d.ts +15 -0
  30. package/dist/core/embeddings/exact-search.js +27 -0
  31. package/dist/core/embeddings/types.d.ts +4 -0
  32. package/dist/core/embeddings/types.js +2 -0
  33. package/dist/core/group/config-parser.js +2 -0
  34. package/dist/core/group/matching.d.ts +3 -3
  35. package/dist/core/group/matching.js +46 -6
  36. package/dist/core/group/storage.js +2 -0
  37. package/dist/core/group/sync.js +1 -1
  38. package/dist/core/group/types.d.ts +18 -0
  39. package/dist/core/ingestion/call-processor.d.ts +3 -3
  40. package/dist/core/ingestion/call-processor.js +58 -65
  41. package/dist/core/ingestion/constants.d.ts +4 -3
  42. package/dist/core/ingestion/constants.js +8 -3
  43. package/dist/core/ingestion/finalize-orchestrator.js +6 -3
  44. package/dist/core/ingestion/heritage-processor.js +2 -2
  45. package/dist/core/ingestion/import-processor.js +1 -1
  46. package/dist/core/ingestion/language-provider.d.ts +8 -0
  47. package/dist/core/ingestion/languages/csharp/captures.js +4 -1
  48. package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +14 -13
  49. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +62 -50
  50. package/dist/core/ingestion/languages/python/captures.js +9 -1
  51. package/dist/core/ingestion/languages/python/index.d.ts +1 -1
  52. package/dist/core/ingestion/languages/python/index.js +1 -1
  53. package/dist/core/ingestion/languages/python/simple-hooks.d.ts +3 -1
  54. package/dist/core/ingestion/languages/python/simple-hooks.js +8 -0
  55. package/dist/core/ingestion/languages/python.js +28 -1
  56. package/dist/core/ingestion/languages/swift.js +14 -0
  57. package/dist/core/ingestion/languages/typescript/arity-metadata.d.ts +59 -0
  58. package/dist/core/ingestion/languages/typescript/arity-metadata.js +103 -0
  59. package/dist/core/ingestion/languages/typescript/arity.d.ts +37 -0
  60. package/dist/core/ingestion/languages/typescript/arity.js +54 -0
  61. package/dist/core/ingestion/languages/typescript/cache-stats.d.ts +17 -0
  62. package/dist/core/ingestion/languages/typescript/cache-stats.js +28 -0
  63. package/dist/core/ingestion/languages/typescript/captures.d.ts +28 -0
  64. package/dist/core/ingestion/languages/typescript/captures.js +451 -0
  65. package/dist/core/ingestion/languages/typescript/import-decomposer.d.ts +49 -0
  66. package/dist/core/ingestion/languages/typescript/import-decomposer.js +371 -0
  67. package/dist/core/ingestion/languages/typescript/import-target.d.ts +50 -0
  68. package/dist/core/ingestion/languages/typescript/import-target.js +61 -0
  69. package/dist/core/ingestion/languages/typescript/index.d.ts +94 -0
  70. package/dist/core/ingestion/languages/typescript/index.js +94 -0
  71. package/dist/core/ingestion/languages/typescript/interpret.d.ts +35 -0
  72. package/dist/core/ingestion/languages/typescript/interpret.js +317 -0
  73. package/dist/core/ingestion/languages/typescript/merge-bindings.d.ts +62 -0
  74. package/dist/core/ingestion/languages/typescript/merge-bindings.js +158 -0
  75. package/dist/core/ingestion/languages/typescript/query.d.ts +77 -0
  76. package/dist/core/ingestion/languages/typescript/query.js +778 -0
  77. package/dist/core/ingestion/languages/typescript/receiver-binding.d.ts +59 -0
  78. package/dist/core/ingestion/languages/typescript/receiver-binding.js +171 -0
  79. package/dist/core/ingestion/languages/typescript/scope-resolver.d.ts +16 -0
  80. package/dist/core/ingestion/languages/typescript/scope-resolver.js +113 -0
  81. package/dist/core/ingestion/languages/typescript/simple-hooks.d.ts +71 -0
  82. package/dist/core/ingestion/languages/typescript/simple-hooks.js +131 -0
  83. package/dist/core/ingestion/languages/typescript.js +19 -0
  84. package/dist/core/ingestion/method-extractors/configs/swift.js +3 -4
  85. package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +14 -1
  86. package/dist/core/ingestion/parsing-processor.js +20 -9
  87. package/dist/core/ingestion/pipeline-phases/processes.js +9 -4
  88. package/dist/core/ingestion/pipeline-phases/tools.d.ts +1 -0
  89. package/dist/core/ingestion/pipeline-phases/tools.js +10 -4
  90. package/dist/core/ingestion/registry-primary-flag.d.ts +3 -1
  91. package/dist/core/ingestion/registry-primary-flag.js +4 -1
  92. package/dist/core/ingestion/scope-extractor-bridge.d.ts +5 -2
  93. package/dist/core/ingestion/scope-extractor-bridge.js +7 -2
  94. package/dist/core/ingestion/scope-extractor.js +19 -18
  95. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +73 -11
  96. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +48 -10
  97. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +283 -14
  98. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.d.ts +23 -2
  99. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +109 -37
  100. package/dist/core/ingestion/scope-resolution/passes/mro.js +3 -1
  101. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +13 -5
  102. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +11 -2
  103. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
  104. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +8 -0
  105. package/dist/core/ingestion/scope-resolution/pipeline/run.js +21 -5
  106. package/dist/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.d.ts +39 -0
  107. package/dist/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +65 -0
  108. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +54 -11
  109. package/dist/core/ingestion/scope-resolution/scope/walkers.js +105 -30
  110. package/dist/core/ingestion/type-extractors/swift.js +7 -4
  111. package/dist/core/ingestion/utils/ast-helpers.d.ts +2 -0
  112. package/dist/core/ingestion/utils/ast-helpers.js +12 -0
  113. package/dist/core/ingestion/utils/env.d.ts +10 -0
  114. package/dist/core/ingestion/utils/env.js +14 -0
  115. package/dist/core/ingestion/workers/parse-worker.d.ts +1 -0
  116. package/dist/core/ingestion/workers/parse-worker.js +15 -9
  117. package/dist/core/ingestion/workers/worker-pool.d.ts +11 -4
  118. package/dist/core/ingestion/workers/worker-pool.js +244 -48
  119. package/dist/core/lbug/extension-loader.d.ts +86 -0
  120. package/dist/core/lbug/extension-loader.js +184 -0
  121. package/dist/core/lbug/lbug-adapter.d.ts +18 -17
  122. package/dist/core/lbug/lbug-adapter.js +45 -73
  123. package/dist/core/lbug/pool-adapter.js +10 -28
  124. package/dist/core/platform/capabilities.d.ts +24 -0
  125. package/dist/core/platform/capabilities.js +54 -0
  126. package/dist/core/run-analyze.js +36 -9
  127. package/dist/core/search/bm25-index.d.ts +0 -17
  128. package/dist/core/search/bm25-index.js +10 -118
  129. package/dist/core/search/fts-indexes.d.ts +1 -0
  130. package/dist/core/search/fts-indexes.js +7 -0
  131. package/dist/core/search/fts-schema.d.ts +6 -0
  132. package/dist/core/search/fts-schema.js +7 -0
  133. package/dist/mcp/core/embedder.js +11 -4
  134. package/dist/mcp/local/local-backend.js +50 -15
  135. package/dist/server/api.d.ts +5 -0
  136. package/dist/server/api.js +113 -0
  137. package/hooks/claude/gitnexus-hook.cjs +11 -1
  138. package/package.json +6 -5
  139. package/scripts/build-tree-sitter-dart.cjs +42 -0
  140. package/scripts/build-tree-sitter-proto.cjs +1 -1
  141. package/scripts/build.js +22 -2
  142. package/scripts/install-duckdb-extension.mjs +37 -0
  143. package/vendor/tree-sitter-dart/README.md +18 -0
  144. package/vendor/tree-sitter-dart/binding.gyp +31 -0
  145. package/vendor/tree-sitter-dart/bindings/node/binding.cc +20 -0
  146. package/vendor/tree-sitter-dart/bindings/node/index.d.ts +28 -0
  147. package/vendor/tree-sitter-dart/bindings/node/index.js +7 -0
  148. package/vendor/tree-sitter-dart/grammar.js +2895 -0
  149. package/vendor/tree-sitter-dart/package.json +18 -0
  150. package/vendor/tree-sitter-dart/queries/highlights.scm +246 -0
  151. package/vendor/tree-sitter-dart/queries/tags.scm +92 -0
  152. package/vendor/tree-sitter-dart/queries/test.scm +1 -0
  153. package/vendor/tree-sitter-dart/src/grammar.json +12459 -0
  154. package/vendor/tree-sitter-dart/src/node-types.json +15055 -0
  155. package/vendor/tree-sitter-dart/src/parser.c +196127 -0
  156. package/vendor/tree-sitter-dart/src/scanner.c +130 -0
  157. package/vendor/tree-sitter-dart/src/tree_sitter/alloc.h +54 -0
  158. package/vendor/tree-sitter-dart/src/tree_sitter/array.h +290 -0
  159. package/vendor/tree-sitter-dart/src/tree_sitter/parser.h +265 -0
  160. package/vendor/tree-sitter-swift/LICENSE +21 -0
  161. package/vendor/tree-sitter-swift/README.md +139 -0
  162. package/vendor/tree-sitter-swift/bindings/node/index.d.ts +28 -0
  163. package/vendor/tree-sitter-swift/bindings/node/index.js +7 -0
  164. package/vendor/tree-sitter-swift/package.json +28 -0
  165. package/vendor/tree-sitter-swift/prebuilds/darwin-arm64/tree-sitter-swift.node +0 -0
  166. package/vendor/tree-sitter-swift/prebuilds/darwin-x64/tree-sitter-swift.node +0 -0
  167. package/vendor/tree-sitter-swift/prebuilds/linux-arm64/tree-sitter-swift.node +0 -0
  168. package/vendor/tree-sitter-swift/prebuilds/linux-x64/tree-sitter-swift.node +0 -0
  169. package/vendor/tree-sitter-swift/prebuilds/win32-arm64/tree-sitter-swift.node +0 -0
  170. package/vendor/tree-sitter-swift/prebuilds/win32-x64/tree-sitter-swift.node +0 -0
  171. package/vendor/tree-sitter-swift/src/node-types.json +30694 -0
  172. package/web/assets/agent-DaprsFSX.js +597 -0
  173. package/web/assets/architecture-YZFGNWBL-S5CXDPWN-DEdGaPg2.js +1 -0
  174. package/web/assets/architectureDiagram-EMZXCZ2Q-Domyk_gO.js +36 -0
  175. package/web/assets/blockDiagram-IGV67L2C-B_2kD7tM.js +132 -0
  176. package/web/assets/c4Diagram-DFAF54RM-BhJJW8Gg.js +10 -0
  177. package/web/assets/chunk-3GS5O3IE-jlWIjPsl.js +231 -0
  178. package/web/assets/chunk-3YCYZ6SJ-Blq_IzZs.js +1 -0
  179. package/web/assets/chunk-6NTNNK5N-DyPc58pp.js +1 -0
  180. package/web/assets/chunk-7RZVMHOQ-BdIU-RGO.js +321 -0
  181. package/web/assets/chunk-A34GCYZU-BI2i_LdU.js +1 -0
  182. package/web/assets/chunk-AEOMTBSW-D7qjBMHW.js +1 -0
  183. package/web/assets/chunk-CilyBKbf.js +1 -0
  184. package/web/assets/chunk-DJ7UZH7F-i11ywiBl.js +1 -0
  185. package/web/assets/chunk-DKKBVRCY-1SffGI1N.js +4 -0
  186. package/web/assets/chunk-DU5LTGQ6-DaPeiwD5.js +1 -0
  187. package/web/assets/chunk-FXACKDTF-uhhi2PC2.js +159 -0
  188. package/web/assets/chunk-H3VCZNTA-IchcISDt.js +1 -0
  189. package/web/assets/chunk-HN6EAY2L-D7ZFMNrB.js +1 -0
  190. package/web/assets/chunk-KSICW3F5-C2tZmXwv.js +15 -0
  191. package/web/assets/chunk-O5ABG6QK-Bt-Km84H.js +1 -0
  192. package/web/assets/chunk-PK6DOVAG-ChlWY0BQ.js +206 -0
  193. package/web/assets/chunk-RNJOYNJ4-B724K7cW.js +1 -0
  194. package/web/assets/chunk-RWUO3TPN-DYn1XriD.js +1 -0
  195. package/web/assets/chunk-TBF5ZNIQ-DKtDz6ae.js +1 -0
  196. package/web/assets/chunk-TU3PZOEN-DE5Qhc0N.js +1 -0
  197. package/web/assets/chunk-TYMNRAUI-g1h33cq-.js +1 -0
  198. package/web/assets/chunk-VELTKBKT-C9dVN39o.js +1 -0
  199. package/web/assets/chunk-W7ZLLLMY-Du-Hb9yb.js +1 -0
  200. package/web/assets/chunk-WSB5WSVC-B123clsZ.js +1 -0
  201. package/web/assets/chunk-XGPFEOL4-BR7Eue38.js +1 -0
  202. package/web/assets/classDiagram-PPOCWD7C-BglfKSs_.js +1 -0
  203. package/web/assets/classDiagram-v2-23LJLIIU-BSzTM28O.js +1 -0
  204. package/web/assets/context-builder-CqQNhRj1.js +15 -0
  205. package/web/assets/cose-bilkent-PNC4W37J-DCfErU-A.js +1 -0
  206. package/web/assets/dagre-E77IOHMT-tDRRhDoN.js +4 -0
  207. package/web/assets/diagram-H7BISOXX-CUVHlmAh.js +43 -0
  208. package/web/assets/diagram-JC5VWROH-BoyOxulB.js +24 -0
  209. package/web/assets/diagram-LXUTUG65-osr9hb7N.js +10 -0
  210. package/web/assets/diagram-WEHSV5V5-d8nUqS39.js +24 -0
  211. package/web/assets/erDiagram-GCSMX5X6-b-IwOhPS.js +85 -0
  212. package/web/assets/flowDiagram-OTCZ4VVT-Ott2Q0AP.js +162 -0
  213. package/web/assets/ganttDiagram-MUNLMDZQ-BYtgN_5s.js +292 -0
  214. package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-CFyBIGZq.js +1 -0
  215. package/web/assets/gitGraphDiagram-3HKGZ4G3-CsVD2gn4.js +106 -0
  216. package/web/assets/index-BleGLU8S.css +2 -0
  217. package/web/assets/index-C_xK08EW.js +885 -0
  218. package/web/assets/info-OMHHGYJF-BF2H5H6G-yjAxKEzh.js +1 -0
  219. package/web/assets/infoDiagram-MN7RKWGX-DXK0Unn5.js +2 -0
  220. package/web/assets/ishikawaDiagram-YMYX4NHK-CXsnC2FA.js +70 -0
  221. package/web/assets/journeyDiagram-SO5T7YLQ-BzZ07B-X.js +139 -0
  222. package/web/assets/kanban-definition-LJHFXRCJ-C6_EpAd9.js +89 -0
  223. package/web/assets/katex-GD7MH7QM-CJiOjBBJ.js +261 -0
  224. package/web/assets/mindmap-definition-2EUWGEK5-CCYGWZ1m.js +96 -0
  225. package/web/assets/packet-4T2RLAQJ-EV4IVRXR-B8k4E3IT.js +1 -0
  226. package/web/assets/pie-ZZUOXDRM-N23DN5KN-DdvfY118.js +1 -0
  227. package/web/assets/pieDiagram-3IATQBI2-RyvRlQb4.js +30 -0
  228. package/web/assets/quadrantDiagram-E256RVCF-Bfb6sxCx.js +7 -0
  229. package/web/assets/radar-PYXPWWZC-P6TP7ZYP-1EEDC_yU.js +1 -0
  230. package/web/assets/requirementDiagram-M5DCFWZL-DjvHDyvN.js +84 -0
  231. package/web/assets/sankeyDiagram-L3NBLAOT-CBCbbl8s.js +10 -0
  232. package/web/assets/sequenceDiagram-ZOUHS735-BscU8TUR.js +157 -0
  233. package/web/assets/stateDiagram-MLPALWAM-CJusEK2D.js +1 -0
  234. package/web/assets/stateDiagram-v2-B5LQ5ZB2-DImJ3PXD.js +1 -0
  235. package/web/assets/timeline-definition-5SPVSISX-DigPA1X8.js +120 -0
  236. package/web/assets/treeView-SZITEDCU-5DXDK3XO-CzPDt3aG.js +1 -0
  237. package/web/assets/treemap-W4RFUUIX-WYLRDWKO-B9Iqiorr.js +1 -0
  238. package/web/assets/vennDiagram-IE5QUKF5-C91UkZIf.js +34 -0
  239. package/web/assets/wardley-RL74JXVD-BCRCBASE-x42Qw7hp.js +1 -0
  240. package/web/assets/wardleyDiagram-XU3VSMPF-DloBhI0U.js +20 -0
  241. package/web/assets/xychartDiagram-ZHJ5623Y-BGWJvgwI.js +7 -0
  242. package/web/index.html +21 -0
  243. package/scripts/patch-tree-sitter-swift.cjs +0 -78
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Decompose a TypeScript `import_statement` / re-export `export_statement` /
3
+ * dynamic `call_expression(import)` into one `CaptureMatch` per imported
4
+ * name.
5
+ *
6
+ * Why split here? The `LanguageProvider.interpretImport` contract is
7
+ * one `ParsedImport` per call. Tree-sitter delivers
8
+ *
9
+ * import D, { X as Y, type Z } from './m'
10
+ *
11
+ * as a single `import_statement` match, so without decomposition we'd
12
+ * lose names. The synthesized markers (`@import.kind` / `@import.name`
13
+ * / `@import.alias` / `@import.source`) carry everything
14
+ * `interpretTsImport` needs to recover the `ParsedImport` shape —
15
+ * see `interpret.ts`.
16
+ *
17
+ * Kinds we emit and how `interpret.ts` maps them to `ParsedImport`:
18
+ *
19
+ * - `default` : `import D from './m'` → alias (importedName=default)
20
+ * - `named` : `import { X } from './m'` → named
21
+ * - `named-alias` : `import { X as Y } from './m'` → alias
22
+ * - `namespace` : `import * as N from './m'` → namespace
23
+ * - `reexport` : `export { X } from './m'` → reexport
24
+ * - `reexport-alias` : `export { X as Y } from './m'` → reexport (with alias)
25
+ * - `reexport-wildcard` : `export * from './m'` → wildcard
26
+ * - `reexport-namespace` : `export * as ns from './m'` → namespace (local=ns,imported=source)
27
+ * - `dynamic` : `import('./m')` / `import(x)` → dynamic-resolved or dynamic-unresolved
28
+ *
29
+ * Type-only constructs (`import type { X }`, `import { type X }`,
30
+ * `export type { X }`) emit the same kinds as runtime forms — at the
31
+ * TypeScript scope-resolution layer, types and values share the same
32
+ * lookup; runtime-emission is a downstream concern.
33
+ *
34
+ * Side-effect imports (`import './polyfill'`) produce a single match
35
+ * with `kind: 'side-effect'`. The shared finalize algorithm resolves
36
+ * the target file and emits a file-level IMPORTS edge, but
37
+ * materializes no `BindingRef` (matching the legacy DAG, which counts
38
+ * `import './polyfill'` as a module-reachability dependency only).
39
+ */
40
+ import { findChild, nodeToCapture, syntheticCapture, } from '../../utils/ast-helpers.js';
41
+ /**
42
+ * Decompose an import anchor. Handles three node types:
43
+ *
44
+ * - `import_statement` : all static import forms (incl. side-effect)
45
+ * - `export_statement` (w/ source) : re-exports
46
+ * - `call_expression` (import fn) : dynamic `import()`
47
+ */
48
+ export function splitImportStatement(stmtNode) {
49
+ if (stmtNode.type === 'import_statement')
50
+ return splitImport(stmtNode);
51
+ if (stmtNode.type === 'export_statement')
52
+ return splitReexport(stmtNode);
53
+ if (stmtNode.type === 'call_expression')
54
+ return splitDynamicImport(stmtNode);
55
+ return [];
56
+ }
57
+ // ─── static imports ─────────────────────────────────────────────────────
58
+ function splitImport(stmtNode) {
59
+ // `import_statement` shape:
60
+ // import_clause? "from" string (static form with bindings)
61
+ // string (side-effect `import './m'`)
62
+ //
63
+ // The `source` field is the string literal — we strip its surrounding
64
+ // quotes. An import without an `import_clause` child is side-effect
65
+ // only and still emits one non-binding match.
66
+ const source = extractSource(stmtNode);
67
+ if (source === null)
68
+ return [];
69
+ const importClause = findChild(stmtNode, 'import_clause');
70
+ if (importClause === null) {
71
+ // `import './polyfill'` — no clause, no local binding. Emit a
72
+ // side-effect match so the finalize layer still produces a
73
+ // file-level IMPORTS edge (parity with the legacy DAG).
74
+ return [
75
+ buildImportMatch(stmtNode, {
76
+ kind: 'side-effect',
77
+ source,
78
+ name: '',
79
+ atNode: stmtNode,
80
+ }),
81
+ ];
82
+ }
83
+ const out = [];
84
+ // An import_clause can have any combination of:
85
+ // - leading identifier (default import)
86
+ // - namespace_import (* as N)
87
+ // - named_imports ({ X, Y as Z })
88
+ for (let i = 0; i < importClause.namedChildCount; i++) {
89
+ const child = importClause.namedChild(i);
90
+ if (child === null)
91
+ continue;
92
+ if (child.type === 'identifier') {
93
+ // Default import: `import D from './m'`.
94
+ out.push(buildImportMatch(stmtNode, {
95
+ kind: 'default',
96
+ source,
97
+ name: 'default',
98
+ alias: child.text,
99
+ atNode: child,
100
+ }));
101
+ continue;
102
+ }
103
+ if (child.type === 'namespace_import') {
104
+ // `* as N` — the identifier child is the local binding.
105
+ const aliasId = findChild(child, 'identifier');
106
+ if (aliasId !== null) {
107
+ out.push(buildImportMatch(stmtNode, {
108
+ kind: 'namespace',
109
+ source,
110
+ name: source,
111
+ alias: aliasId.text,
112
+ atNode: child,
113
+ }));
114
+ }
115
+ continue;
116
+ }
117
+ if (child.type === 'named_imports') {
118
+ for (let j = 0; j < child.namedChildCount; j++) {
119
+ const spec = child.namedChild(j);
120
+ if (spec === null || spec.type !== 'import_specifier')
121
+ continue;
122
+ const decomposed = decomposeNamedSpecifier(spec, source, stmtNode);
123
+ if (decomposed !== null)
124
+ out.push(decomposed);
125
+ }
126
+ continue;
127
+ }
128
+ // Other children (e.g. `type` keyword token for `import type { ... }`)
129
+ // are ignored — they carry no per-specifier info; we fold type-only
130
+ // semantics into the same emitted kinds.
131
+ }
132
+ return out;
133
+ }
134
+ /**
135
+ * Decompose a single `import_specifier` into one match. Handles:
136
+ *
137
+ * - `{ X }` → named
138
+ * - `{ X as Y }` → named-alias
139
+ * - `{ type X }` → named (type-only; same shape)
140
+ * - `{ type X as Y }` → named-alias (type-only)
141
+ */
142
+ function decomposeNamedSpecifier(spec, source, stmtNode) {
143
+ // `import_specifier` layout:
144
+ // name: identifier
145
+ // alias: identifier? (only when `as` is present)
146
+ // plus an optional `type` keyword token in front (per-specifier type-only)
147
+ //
148
+ // tree-sitter-typescript exposes `name` and `alias` as named fields.
149
+ // If `name` is absent, fail closed rather than guessing positionally:
150
+ // binding the alias as the imported name would invert the edge.
151
+ const nameNode = spec.childForFieldName('name');
152
+ const aliasNode = spec.childForFieldName('alias');
153
+ if (nameNode === null)
154
+ return null;
155
+ const name = nameNode.text;
156
+ if (aliasNode !== null && aliasNode.startIndex !== nameNode.startIndex) {
157
+ return buildImportMatch(stmtNode, {
158
+ kind: 'named-alias',
159
+ source,
160
+ name,
161
+ alias: aliasNode.text,
162
+ atNode: spec,
163
+ });
164
+ }
165
+ return buildImportMatch(stmtNode, {
166
+ kind: 'named',
167
+ source,
168
+ name,
169
+ atNode: spec,
170
+ });
171
+ }
172
+ // ─── re-exports ──────────────────────────────────────────────────────────
173
+ function splitReexport(stmtNode) {
174
+ // `export_statement` with a `source:` field is a re-export. Forms:
175
+ //
176
+ // export { X, Y as Z } from './m' → export_clause children
177
+ // export * from './m' → no clause
178
+ // export * as ns from './m' → namespace_export child
179
+ // export type { X } from './m' → same clause path
180
+ //
181
+ // Local `export { X }` (no `from`) is visibility metadata, not an
182
+ // import; the captures-layer query guards with a `source: (string)`
183
+ // predicate so we always have a source here — but we defend
184
+ // structurally anyway.
185
+ const source = extractSource(stmtNode);
186
+ if (source === null)
187
+ return [];
188
+ const exportClause = findChild(stmtNode, 'export_clause');
189
+ if (exportClause !== null) {
190
+ const out = [];
191
+ for (let i = 0; i < exportClause.namedChildCount; i++) {
192
+ const spec = exportClause.namedChild(i);
193
+ if (spec === null || spec.type !== 'export_specifier')
194
+ continue;
195
+ const decomposed = decomposeReexportSpecifier(spec, source, stmtNode);
196
+ if (decomposed !== null)
197
+ out.push(decomposed);
198
+ }
199
+ return out;
200
+ }
201
+ // `export * as ns from './m'` — tree-sitter-typescript emits a
202
+ // `namespace_export` child whose identifier is the local re-export
203
+ // name. Two facts are emitted:
204
+ //
205
+ // 1. An `@import.statement` (kind `reexport-namespace`) so finalize
206
+ // knows the barrel imports `./m` as `ns` (binds `ns` locally
207
+ // inside the barrel for consumers like `barrel.ts` calling
208
+ // `ns.X()`).
209
+ // 2. A synthetic `@declaration.namespace` so the central
210
+ // scope-extractor adds a `Namespace` SymbolDefinition for `ns`
211
+ // to the barrel's `localDefs`. Without this, downstream files
212
+ // doing `import { ns } from './barrel'` cannot resolve `ns`:
213
+ // `findExportByName` and the precomputed re-export closure only
214
+ // consult `localDefs` / `reexport` / `wildcard` drafts, never
215
+ // `namespace`-kind imports. The synthetic declaration fixes that
216
+ // without growing the shared finalizer's surface.
217
+ const namespaceExport = findChild(stmtNode, 'namespace_export');
218
+ if (namespaceExport !== null) {
219
+ const aliasId = findChild(namespaceExport, 'identifier');
220
+ if (aliasId !== null) {
221
+ return [
222
+ buildImportMatch(stmtNode, {
223
+ kind: 'reexport-namespace',
224
+ source,
225
+ name: source,
226
+ alias: aliasId.text,
227
+ atNode: namespaceExport,
228
+ }),
229
+ buildNamespaceDeclarationMatch(namespaceExport, aliasId),
230
+ ];
231
+ }
232
+ }
233
+ // `export * from './m'` — no clause, no namespace_export. The bare
234
+ // `*` token is the only remaining marker; we don't need to inspect
235
+ // it since the shape alone says "wildcard".
236
+ return [
237
+ buildImportMatch(stmtNode, {
238
+ kind: 'reexport-wildcard',
239
+ source,
240
+ name: '*',
241
+ atNode: stmtNode,
242
+ }),
243
+ ];
244
+ }
245
+ function decomposeReexportSpecifier(spec, source, stmtNode) {
246
+ const nameNode = spec.childForFieldName('name');
247
+ const aliasNode = spec.childForFieldName('alias');
248
+ if (nameNode === null)
249
+ return null;
250
+ const name = nameNode.text;
251
+ if (aliasNode !== null && aliasNode.startIndex !== nameNode.startIndex) {
252
+ return buildImportMatch(stmtNode, {
253
+ kind: 'reexport-alias',
254
+ source,
255
+ name,
256
+ alias: aliasNode.text,
257
+ atNode: spec,
258
+ });
259
+ }
260
+ return buildImportMatch(stmtNode, {
261
+ kind: 'reexport',
262
+ source,
263
+ name,
264
+ atNode: spec,
265
+ });
266
+ }
267
+ // ─── dynamic imports ─────────────────────────────────────────────────────
268
+ function splitDynamicImport(callNode) {
269
+ // `call_expression` shape for dynamic imports:
270
+ // function: (import) — named leaf node in tree-sitter-typescript
271
+ // arguments: (arguments (string) ...) — first arg is the path
272
+ //
273
+ // When the argument is a string literal, preserve its value. When it's
274
+ // anything else (variable, template literal, member access), surface
275
+ // the raw text for diagnostics and let `interpretTsImport` emit
276
+ // `dynamic-unresolved` with a `targetRaw` hint.
277
+ const args = callNode.childForFieldName('arguments');
278
+ if (args === null) {
279
+ return [
280
+ buildImportMatch(callNode, {
281
+ kind: 'dynamic',
282
+ source: null,
283
+ name: '',
284
+ atNode: callNode,
285
+ }),
286
+ ];
287
+ }
288
+ const firstArg = args.namedChild(0);
289
+ if (firstArg === null) {
290
+ return [
291
+ buildImportMatch(callNode, {
292
+ kind: 'dynamic',
293
+ source: null,
294
+ name: '',
295
+ atNode: callNode,
296
+ }),
297
+ ];
298
+ }
299
+ if (firstArg.type === 'string') {
300
+ const source = stripQuotes(firstArg.text);
301
+ return [
302
+ buildImportMatch(callNode, {
303
+ kind: 'dynamic',
304
+ source,
305
+ name: '',
306
+ atNode: callNode,
307
+ literalSource: true,
308
+ }),
309
+ ];
310
+ }
311
+ // Non-literal argument — preserve source text so downstream
312
+ // diagnostics show what the user wrote.
313
+ return [
314
+ buildImportMatch(callNode, {
315
+ kind: 'dynamic',
316
+ source: firstArg.text,
317
+ name: '',
318
+ atNode: callNode,
319
+ }),
320
+ ];
321
+ }
322
+ // ─── helpers ─────────────────────────────────────────────────────────────
323
+ function extractSource(stmtNode) {
324
+ // Both `import_statement` and `export_statement` expose the module
325
+ // path through the `source:` field. It's typed as `string` in the
326
+ // grammar; we strip its surrounding quotes.
327
+ const sourceField = stmtNode.childForFieldName('source');
328
+ if (sourceField === null || sourceField.type !== 'string')
329
+ return null;
330
+ return stripQuotes(sourceField.text);
331
+ }
332
+ function stripQuotes(raw) {
333
+ const trimmed = raw.trim();
334
+ if (trimmed.length < 2)
335
+ return trimmed;
336
+ const first = trimmed.charAt(0);
337
+ const last = trimmed.charAt(trimmed.length - 1);
338
+ if ((first === '"' && last === '"') ||
339
+ (first === "'" && last === "'") ||
340
+ (first === '`' && last === '`')) {
341
+ return trimmed.slice(1, -1);
342
+ }
343
+ return trimmed;
344
+ }
345
+ function buildImportMatch(stmtNode, spec) {
346
+ const m = {
347
+ '@import.statement': nodeToCapture('@import.statement', stmtNode),
348
+ '@import.kind': syntheticCapture('@import.kind', spec.atNode, spec.kind),
349
+ '@import.name': syntheticCapture('@import.name', spec.atNode, spec.name),
350
+ };
351
+ if (spec.source !== null) {
352
+ m['@import.source'] = syntheticCapture('@import.source', spec.atNode, spec.source);
353
+ }
354
+ if (spec.alias !== undefined) {
355
+ m['@import.alias'] = syntheticCapture('@import.alias', spec.atNode, spec.alias);
356
+ }
357
+ if (spec.literalSource === true) {
358
+ m['@import.literal'] = syntheticCapture('@import.literal', spec.atNode, '');
359
+ }
360
+ return m;
361
+ }
362
+ /** Synthesize a `@declaration.namespace` match for `export * as ns from './m'`.
363
+ * The central scope-extractor turns this into a `SymbolDefinition` of type
364
+ * `Namespace` in the barrel's `localDefs`, which makes `findExportByName`
365
+ * resolve `ns` for downstream `import { ns } from './barrel'` consumers. */
366
+ function buildNamespaceDeclarationMatch(namespaceExportNode, aliasId) {
367
+ return {
368
+ '@declaration.namespace': nodeToCapture('@declaration.namespace', namespaceExportNode),
369
+ '@declaration.name': nodeToCapture('@declaration.name', aliasId),
370
+ };
371
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Adapter from `(ParsedImport, WorkspaceIndex)` → concrete file path.
3
+ *
4
+ * Delegates to the existing standard-strategy resolver
5
+ * (`resolveImportPath`) so tsconfig path aliases (`@/`, `~/`, …) and
6
+ * suffix-based resolution follow the same rules as the legacy path.
7
+ *
8
+ * The `WorkspaceIndex` is opaque at the shared contract layer; we
9
+ * narrow it to a TypeScript-shaped context that carries `fromFile` +
10
+ * the full `allFilePaths` set + the optional `tsconfigPaths` the
11
+ * resolver reads.
12
+ *
13
+ * Returning `null` lets the finalize algorithm mark the edge as
14
+ * `linkStatus: 'unresolved'`.
15
+ */
16
+ import type { ParsedImport, WorkspaceIndex } from '../../../../_shared/index.js';
17
+ import { SupportedLanguages } from '../../../../_shared/index.js';
18
+ import type { TsconfigPaths } from '../../language-config.js';
19
+ export interface TsResolveContext {
20
+ readonly fromFile: string;
21
+ /** Mutable `Set` because the standard resolver consumes `Set<string>`.
22
+ * Callers holding a `ReadonlySet` should copy via `new Set(...)`. */
23
+ readonly allFilePaths: Set<string>;
24
+ /** Repo file list, normalized (lowercased) for suffix matching. May
25
+ * be supplied by the orchestrator; if absent we derive it on the
26
+ * fly from `allFilePaths`. */
27
+ readonly allFileList?: readonly string[];
28
+ readonly normalizedFileList?: readonly string[];
29
+ /** Per-call resolution cache to dedupe repeated lookups. */
30
+ readonly resolveCache?: Map<string, string | null>;
31
+ /** Parsed tsconfig path-aliases. `null` = no aliases configured. */
32
+ readonly tsconfigPaths?: TsconfigPaths | null;
33
+ /** JavaScript vs TypeScript switch — affects the extensions the
34
+ * resolver tries. Defaults to TypeScript. */
35
+ readonly language?: SupportedLanguages.TypeScript | SupportedLanguages.JavaScript;
36
+ }
37
+ export declare function resolveTsImportTarget(parsedImport: ParsedImport, workspaceIndex: WorkspaceIndex): string | null;
38
+ /**
39
+ * Resolve a raw module-path string to a workspace file path using the
40
+ * same standard-strategy resolver as the legacy DAG. Operates directly on
41
+ * the source string without requiring a `ParsedImport`, so the
42
+ * `ScopeResolver.resolveImportTarget` adapter doesn't need to construct
43
+ * a fake `ParsedImport` to reach the resolver.
44
+ *
45
+ * Returns `null` when:
46
+ * - the context is malformed (missing `fromFile` / `allFilePaths`)
47
+ * - `targetRaw` is empty
48
+ * - the resolver finds no matching file
49
+ */
50
+ export declare function resolveTsTarget(targetRaw: string, ctx: TsResolveContext): string | null;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Adapter from `(ParsedImport, WorkspaceIndex)` → concrete file path.
3
+ *
4
+ * Delegates to the existing standard-strategy resolver
5
+ * (`resolveImportPath`) so tsconfig path aliases (`@/`, `~/`, …) and
6
+ * suffix-based resolution follow the same rules as the legacy path.
7
+ *
8
+ * The `WorkspaceIndex` is opaque at the shared contract layer; we
9
+ * narrow it to a TypeScript-shaped context that carries `fromFile` +
10
+ * the full `allFilePaths` set + the optional `tsconfigPaths` the
11
+ * resolver reads.
12
+ *
13
+ * Returning `null` lets the finalize algorithm mark the edge as
14
+ * `linkStatus: 'unresolved'`.
15
+ */
16
+ import { SupportedLanguages } from '../../../../_shared/index.js';
17
+ import { resolveImportPath } from '../../import-resolvers/standard.js';
18
+ export function resolveTsImportTarget(parsedImport, workspaceIndex) {
19
+ const ctx = narrowTsContext(workspaceIndex);
20
+ if (ctx === null)
21
+ return null;
22
+ // Dynamic imports carry `targetRaw` only for diagnostics; when the
23
+ // expression isn't a string literal we can't resolve a file.
24
+ // A string-literal dynamic import (`import('./m')`) resolves like a
25
+ // static import — fall through to the shared path resolver.
26
+ if (parsedImport.kind === 'dynamic-unresolved' && parsedImport.targetRaw === null)
27
+ return null;
28
+ if (parsedImport.targetRaw === null || parsedImport.targetRaw === '')
29
+ return null;
30
+ return resolveTsTarget(parsedImport.targetRaw, ctx);
31
+ }
32
+ /**
33
+ * Resolve a raw module-path string to a workspace file path using the
34
+ * same standard-strategy resolver as the legacy DAG. Operates directly on
35
+ * the source string without requiring a `ParsedImport`, so the
36
+ * `ScopeResolver.resolveImportTarget` adapter doesn't need to construct
37
+ * a fake `ParsedImport` to reach the resolver.
38
+ *
39
+ * Returns `null` when:
40
+ * - the context is malformed (missing `fromFile` / `allFilePaths`)
41
+ * - `targetRaw` is empty
42
+ * - the resolver finds no matching file
43
+ */
44
+ export function resolveTsTarget(targetRaw, ctx) {
45
+ if (targetRaw === '')
46
+ return null;
47
+ const language = ctx.language ?? SupportedLanguages.TypeScript;
48
+ const allFileList = ctx.allFileList ?? Array.from(ctx.allFilePaths);
49
+ const normalizedFileList = ctx.normalizedFileList ?? allFileList.map((f) => f.toLowerCase());
50
+ const resolveCache = ctx.resolveCache ?? new Map();
51
+ return resolveImportPath(ctx.fromFile, targetRaw, ctx.allFilePaths, allFileList, normalizedFileList, resolveCache, language, ctx.tsconfigPaths ?? null);
52
+ }
53
+ function narrowTsContext(workspaceIndex) {
54
+ const ctx = workspaceIndex;
55
+ if (ctx === undefined ||
56
+ typeof ctx.fromFile !== 'string' ||
57
+ !(ctx.allFilePaths instanceof Set)) {
58
+ return null;
59
+ }
60
+ return ctx;
61
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * TypeScript scope-resolution hooks (RFC #909 Ring 3, RFC §5).
3
+ *
4
+ * Public API barrel. Consumers should import from this file rather
5
+ * than 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` — `emitTsScopeCaptures` orchestrator
11
+ * - `import-decomposer.ts` — each import/re-export/dynamic-import →
12
+ * ParsedImport-shaped captures
13
+ * - `interpret.ts` — capture-match → `ParsedImport` /
14
+ * `ParsedTypeBinding`
15
+ * - `simple-hooks.ts` — `bindingScopeFor` (var hoisting + return-
16
+ * type hoisting), `importOwningScope`
17
+ * (module/namespace default), `receiverBinding`
18
+ * (`this` lookup on Function scope)
19
+ * - `receiver-binding.ts` — synthesize `this` type-bindings on
20
+ * instance-method entry (methods, interface
21
+ * signatures, class-field arrow functions)
22
+ * - `merge-bindings.ts` — TypeScript declaration merging
23
+ * (value / type / namespace spaces) + LEGB
24
+ * tier shadowing
25
+ * - `arity.ts` — TypeScript arity compatibility (rest,
26
+ * optional, default params)
27
+ * - `arity-metadata.ts` — synthesize arity metadata from
28
+ * declarations; includes generics + array-
29
+ * suffix stripping on parameter types
30
+ * - `import-target.ts` — `(ParsedImport, WorkspaceIndex) → file path`
31
+ * adapter delegating to the shared standard
32
+ * resolver (tsconfig paths, node_modules,
33
+ * relative/extension suffix matching)
34
+ * - `cache-stats.ts` — PROF_SCOPE_RESOLUTION cache hit/miss
35
+ * counters
36
+ *
37
+ * ## Known limitations
38
+ *
39
+ * The TypeScript registry-primary path intentionally does NOT resolve
40
+ * the following. Each is a conscious trade-off at migration time.
41
+ *
42
+ * 1. **Type-only import / export separation** — `import type { X }`
43
+ * and `import { X }` produce the same `ParsedImport` shape today;
44
+ * `def.type` on the resolved symbol is the only discriminator.
45
+ * Parity with the legacy path is preserved. Tracking in #927.
46
+ * 2. **Declaration merging for imports** — when `import { Foo }`
47
+ * brings in a symbol that is BOTH a class and a namespace in the
48
+ * source module, we currently surface a single binding per the
49
+ * target `def.type`. Downstream type/value-space lookups still
50
+ * work for the primary space; the other space's members resolve
51
+ * via the same target (class statics reachable via dotted access).
52
+ * 3. **Overload narrowing by argument type** — `@reference.parameter-
53
+ * types` carries static literal types inferred from the callsite
54
+ * (`string`, `number`, `Array`, etc.). Identifier / member-access
55
+ * arguments emit empty strings (unknown type); the registry's
56
+ * narrowing treats them as any-match. Full control-flow type
57
+ * narrowing is out of scope.
58
+ * 4. **Computed member access** — `obj[key]()` / `obj['method']()`
59
+ * is classified as an index-access call; member-call resolution
60
+ * falls back to the identifier-indexed branch and matches only
61
+ * when the key is a string literal.
62
+ * 5. **`this` for nested regular functions inside methods** — our
63
+ * scope-chain lookup returns the enclosing method's `this`, which
64
+ * is technically incorrect at runtime (a non-arrow nested function
65
+ * has its own `this` binding). Accepted false-positive; see
66
+ * `simple-hooks.ts` docstring.
67
+ * 6. **`class_expression` receiver types** — `const C = class { }`
68
+ * skips `this` synthesis when the expression is anonymous (no
69
+ * type name to propagate). `const C = class Named { }` works via
70
+ * the class's own `name` field.
71
+ * 7. **JSX element types** — JSX-specific constructs are ignored by
72
+ * the scope query; component references resolve via regular
73
+ * identifier / member-expression paths.
74
+ * 8. **Ambient module declarations** (`declare module '…'`) — parsed
75
+ * but not indexed at this layer; same as today's legacy path.
76
+ * 9. **Intersection types on parameters** (`(a: A & B)`) — treated
77
+ * as opaque (no strip); overload narrowing on intersections
78
+ * won't match.
79
+ * 10. **`instanceof` member-expression narrowing** — only bare
80
+ * identifiers are narrowed (`user instanceof User`). Member paths
81
+ * such as `user.address instanceof Address` remain unresolved.
82
+ *
83
+ * Shadow-harness corpus parity on `test/integration/resolvers/
84
+ * typescript.test.ts` is the authoritative signal for which of these
85
+ * matter in practice. The CI parity gate blocks any PR that regresses
86
+ * either the legacy or registry-primary run.
87
+ */
88
+ export { emitTsScopeCaptures } from './captures.js';
89
+ export { getTypescriptCaptureCacheStats, resetTypescriptCaptureCacheStats } from './cache-stats.js';
90
+ export { interpretTsImport, interpretTsTypeBinding } from './interpret.js';
91
+ export { typescriptMergeBindings } from './merge-bindings.js';
92
+ export { typescriptArityCompatibility } from './arity.js';
93
+ export { resolveTsImportTarget, resolveTsTarget, type TsResolveContext } from './import-target.js';
94
+ export { tsBindingScopeFor, tsImportOwningScope, tsReceiverBinding } from './simple-hooks.js';
@@ -0,0 +1,94 @@
1
+ /**
2
+ * TypeScript scope-resolution hooks (RFC #909 Ring 3, RFC §5).
3
+ *
4
+ * Public API barrel. Consumers should import from this file rather
5
+ * than 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` — `emitTsScopeCaptures` orchestrator
11
+ * - `import-decomposer.ts` — each import/re-export/dynamic-import →
12
+ * ParsedImport-shaped captures
13
+ * - `interpret.ts` — capture-match → `ParsedImport` /
14
+ * `ParsedTypeBinding`
15
+ * - `simple-hooks.ts` — `bindingScopeFor` (var hoisting + return-
16
+ * type hoisting), `importOwningScope`
17
+ * (module/namespace default), `receiverBinding`
18
+ * (`this` lookup on Function scope)
19
+ * - `receiver-binding.ts` — synthesize `this` type-bindings on
20
+ * instance-method entry (methods, interface
21
+ * signatures, class-field arrow functions)
22
+ * - `merge-bindings.ts` — TypeScript declaration merging
23
+ * (value / type / namespace spaces) + LEGB
24
+ * tier shadowing
25
+ * - `arity.ts` — TypeScript arity compatibility (rest,
26
+ * optional, default params)
27
+ * - `arity-metadata.ts` — synthesize arity metadata from
28
+ * declarations; includes generics + array-
29
+ * suffix stripping on parameter types
30
+ * - `import-target.ts` — `(ParsedImport, WorkspaceIndex) → file path`
31
+ * adapter delegating to the shared standard
32
+ * resolver (tsconfig paths, node_modules,
33
+ * relative/extension suffix matching)
34
+ * - `cache-stats.ts` — PROF_SCOPE_RESOLUTION cache hit/miss
35
+ * counters
36
+ *
37
+ * ## Known limitations
38
+ *
39
+ * The TypeScript registry-primary path intentionally does NOT resolve
40
+ * the following. Each is a conscious trade-off at migration time.
41
+ *
42
+ * 1. **Type-only import / export separation** — `import type { X }`
43
+ * and `import { X }` produce the same `ParsedImport` shape today;
44
+ * `def.type` on the resolved symbol is the only discriminator.
45
+ * Parity with the legacy path is preserved. Tracking in #927.
46
+ * 2. **Declaration merging for imports** — when `import { Foo }`
47
+ * brings in a symbol that is BOTH a class and a namespace in the
48
+ * source module, we currently surface a single binding per the
49
+ * target `def.type`. Downstream type/value-space lookups still
50
+ * work for the primary space; the other space's members resolve
51
+ * via the same target (class statics reachable via dotted access).
52
+ * 3. **Overload narrowing by argument type** — `@reference.parameter-
53
+ * types` carries static literal types inferred from the callsite
54
+ * (`string`, `number`, `Array`, etc.). Identifier / member-access
55
+ * arguments emit empty strings (unknown type); the registry's
56
+ * narrowing treats them as any-match. Full control-flow type
57
+ * narrowing is out of scope.
58
+ * 4. **Computed member access** — `obj[key]()` / `obj['method']()`
59
+ * is classified as an index-access call; member-call resolution
60
+ * falls back to the identifier-indexed branch and matches only
61
+ * when the key is a string literal.
62
+ * 5. **`this` for nested regular functions inside methods** — our
63
+ * scope-chain lookup returns the enclosing method's `this`, which
64
+ * is technically incorrect at runtime (a non-arrow nested function
65
+ * has its own `this` binding). Accepted false-positive; see
66
+ * `simple-hooks.ts` docstring.
67
+ * 6. **`class_expression` receiver types** — `const C = class { }`
68
+ * skips `this` synthesis when the expression is anonymous (no
69
+ * type name to propagate). `const C = class Named { }` works via
70
+ * the class's own `name` field.
71
+ * 7. **JSX element types** — JSX-specific constructs are ignored by
72
+ * the scope query; component references resolve via regular
73
+ * identifier / member-expression paths.
74
+ * 8. **Ambient module declarations** (`declare module '…'`) — parsed
75
+ * but not indexed at this layer; same as today's legacy path.
76
+ * 9. **Intersection types on parameters** (`(a: A & B)`) — treated
77
+ * as opaque (no strip); overload narrowing on intersections
78
+ * won't match.
79
+ * 10. **`instanceof` member-expression narrowing** — only bare
80
+ * identifiers are narrowed (`user instanceof User`). Member paths
81
+ * such as `user.address instanceof Address` remain unresolved.
82
+ *
83
+ * Shadow-harness corpus parity on `test/integration/resolvers/
84
+ * typescript.test.ts` is the authoritative signal for which of these
85
+ * matter in practice. The CI parity gate blocks any PR that regresses
86
+ * either the legacy or registry-primary run.
87
+ */
88
+ export { emitTsScopeCaptures } from './captures.js';
89
+ export { getTypescriptCaptureCacheStats, resetTypescriptCaptureCacheStats } from './cache-stats.js';
90
+ export { interpretTsImport, interpretTsTypeBinding } from './interpret.js';
91
+ export { typescriptMergeBindings } from './merge-bindings.js';
92
+ export { typescriptArityCompatibility } from './arity.js';
93
+ export { resolveTsImportTarget, resolveTsTarget } from './import-target.js';
94
+ export { tsBindingScopeFor, tsImportOwningScope, tsReceiverBinding } from './simple-hooks.js';