gitnexus 1.6.8-rc.9 → 1.6.8

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 (430) hide show
  1. package/README.md +3 -3
  2. package/dist/_shared/graph/types.d.ts +31 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/language-detection.d.ts.map +1 -1
  5. package/dist/_shared/language-detection.js +11 -1
  6. package/dist/_shared/language-detection.js.map +1 -1
  7. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  8. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  9. package/dist/_shared/lbug/schema-constants.js +6 -0
  10. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  11. package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
  12. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
  13. package/dist/_shared/scope-resolution/symbol-definition.d.ts +6 -0
  14. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  15. package/dist/cli/ai-context.d.ts +31 -1
  16. package/dist/cli/ai-context.js +18 -16
  17. package/dist/cli/analyze-config.js +11 -0
  18. package/dist/cli/analyze.d.ts +14 -0
  19. package/dist/cli/analyze.js +98 -0
  20. package/dist/cli/embedding-dims.d.ts +33 -0
  21. package/dist/cli/embedding-dims.js +39 -0
  22. package/dist/cli/eval-server.d.ts +8 -0
  23. package/dist/cli/eval-server.js +242 -2
  24. package/dist/cli/help-i18n.js +19 -0
  25. package/dist/cli/i18n/en.d.ts +15 -1
  26. package/dist/cli/i18n/en.js +15 -1
  27. package/dist/cli/i18n/resources.d.ts +29 -1
  28. package/dist/cli/i18n/zh-CN.d.ts +14 -0
  29. package/dist/cli/i18n/zh-CN.js +15 -1
  30. package/dist/cli/index.js +89 -1
  31. package/dist/cli/mcp.d.ts +6 -1
  32. package/dist/cli/mcp.js +26 -1
  33. package/dist/cli/optional-grammars.d.ts +6 -8
  34. package/dist/cli/optional-grammars.js +8 -11
  35. package/dist/cli/setup.d.ts +3 -1
  36. package/dist/cli/setup.js +67 -17
  37. package/dist/cli/skill-gen.js +2 -1
  38. package/dist/cli/tool.d.ts +19 -1
  39. package/dist/cli/tool.js +96 -3
  40. package/dist/core/embeddings/hf-env.d.ts +0 -66
  41. package/dist/core/embeddings/http-client.d.ts +7 -0
  42. package/dist/core/embeddings/http-client.js +5 -3
  43. package/dist/core/embeddings/server-mapping.d.ts +1 -1
  44. package/dist/core/embeddings/server-mapping.js +7 -3
  45. package/dist/core/graph/import-cycles.d.ts +10 -0
  46. package/dist/core/graph/import-cycles.js +103 -0
  47. package/dist/core/group/cross-impact.d.ts +2 -1
  48. package/dist/core/group/cross-impact.js +5 -1
  49. package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
  50. package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
  51. package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
  52. package/dist/core/group/extractors/http-route-extractor.js +22 -4
  53. package/dist/core/group/extractors/include-extractor.js +22 -13
  54. package/dist/core/group/sync.d.ts +27 -1
  55. package/dist/core/group/sync.js +0 -0
  56. package/dist/core/incremental/subgraph-extract.js +18 -1
  57. package/dist/core/ingestion/cfg/cfg-builder.d.ts +114 -0
  58. package/dist/core/ingestion/cfg/cfg-builder.js +196 -0
  59. package/dist/core/ingestion/cfg/collect.d.ts +51 -0
  60. package/dist/core/ingestion/cfg/collect.js +77 -0
  61. package/dist/core/ingestion/cfg/control-dependence.d.ts +58 -0
  62. package/dist/core/ingestion/cfg/control-dependence.js +182 -0
  63. package/dist/core/ingestion/cfg/control-flow-context.d.ts +106 -0
  64. package/dist/core/ingestion/cfg/control-flow-context.js +124 -0
  65. package/dist/core/ingestion/cfg/emit.d.ts +293 -0
  66. package/dist/core/ingestion/cfg/emit.js +646 -0
  67. package/dist/core/ingestion/cfg/post-dominators.d.ts +79 -0
  68. package/dist/core/ingestion/cfg/post-dominators.js +176 -0
  69. package/dist/core/ingestion/cfg/reaching-def-reason-codec.d.ts +106 -0
  70. package/dist/core/ingestion/cfg/reaching-def-reason-codec.js +133 -0
  71. package/dist/core/ingestion/cfg/reaching-defs-graph.d.ts +18 -0
  72. package/dist/core/ingestion/cfg/reaching-defs-graph.js +312 -0
  73. package/dist/core/ingestion/cfg/reaching-defs.d.ts +162 -0
  74. package/dist/core/ingestion/cfg/reaching-defs.js +785 -0
  75. package/dist/core/ingestion/cfg/synthetic-escape.d.ts +124 -0
  76. package/dist/core/ingestion/cfg/synthetic-escape.js +300 -0
  77. package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
  78. package/dist/core/ingestion/cfg/traversal-result.js +2 -0
  79. package/dist/core/ingestion/cfg/types.d.ts +274 -0
  80. package/dist/core/ingestion/cfg/types.js +13 -0
  81. package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.d.ts +111 -0
  82. package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.js +541 -0
  83. package/dist/core/ingestion/cfg/visitors/c-cpp.d.ts +74 -0
  84. package/dist/core/ingestion/cfg/visitors/c-cpp.js +584 -0
  85. package/dist/core/ingestion/cfg/visitors/call-site-harvest.d.ts +195 -0
  86. package/dist/core/ingestion/cfg/visitors/call-site-harvest.js +350 -0
  87. package/dist/core/ingestion/cfg/visitors/csharp-harvest.d.ts +124 -0
  88. package/dist/core/ingestion/cfg/visitors/csharp-harvest.js +589 -0
  89. package/dist/core/ingestion/cfg/visitors/csharp.d.ts +87 -0
  90. package/dist/core/ingestion/cfg/visitors/csharp.js +867 -0
  91. package/dist/core/ingestion/cfg/visitors/dart-harvest.d.ts +278 -0
  92. package/dist/core/ingestion/cfg/visitors/dart-harvest.js +870 -0
  93. package/dist/core/ingestion/cfg/visitors/dart.d.ts +119 -0
  94. package/dist/core/ingestion/cfg/visitors/dart.js +836 -0
  95. package/dist/core/ingestion/cfg/visitors/go-harvest.d.ts +160 -0
  96. package/dist/core/ingestion/cfg/visitors/go-harvest.js +621 -0
  97. package/dist/core/ingestion/cfg/visitors/go.d.ts +108 -0
  98. package/dist/core/ingestion/cfg/visitors/go.js +638 -0
  99. package/dist/core/ingestion/cfg/visitors/java-harvest.d.ts +108 -0
  100. package/dist/core/ingestion/cfg/visitors/java-harvest.js +513 -0
  101. package/dist/core/ingestion/cfg/visitors/java.d.ts +101 -0
  102. package/dist/core/ingestion/cfg/visitors/java.js +812 -0
  103. package/dist/core/ingestion/cfg/visitors/kotlin-harvest.d.ts +253 -0
  104. package/dist/core/ingestion/cfg/visitors/kotlin-harvest.js +719 -0
  105. package/dist/core/ingestion/cfg/visitors/kotlin.d.ts +121 -0
  106. package/dist/core/ingestion/cfg/visitors/kotlin.js +809 -0
  107. package/dist/core/ingestion/cfg/visitors/php-harvest.d.ts +172 -0
  108. package/dist/core/ingestion/cfg/visitors/php-harvest.js +626 -0
  109. package/dist/core/ingestion/cfg/visitors/php.d.ts +96 -0
  110. package/dist/core/ingestion/cfg/visitors/php.js +721 -0
  111. package/dist/core/ingestion/cfg/visitors/python-harvest.d.ts +212 -0
  112. package/dist/core/ingestion/cfg/visitors/python-harvest.js +739 -0
  113. package/dist/core/ingestion/cfg/visitors/python.d.ts +103 -0
  114. package/dist/core/ingestion/cfg/visitors/python.js +558 -0
  115. package/dist/core/ingestion/cfg/visitors/ruby-harvest.d.ts +223 -0
  116. package/dist/core/ingestion/cfg/visitors/ruby-harvest.js +587 -0
  117. package/dist/core/ingestion/cfg/visitors/ruby.d.ts +112 -0
  118. package/dist/core/ingestion/cfg/visitors/ruby.js +756 -0
  119. package/dist/core/ingestion/cfg/visitors/rust-harvest.d.ts +324 -0
  120. package/dist/core/ingestion/cfg/visitors/rust-harvest.js +873 -0
  121. package/dist/core/ingestion/cfg/visitors/rust.d.ts +95 -0
  122. package/dist/core/ingestion/cfg/visitors/rust.js +558 -0
  123. package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.d.ts +87 -0
  124. package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.js +116 -0
  125. package/dist/core/ingestion/cfg/visitors/swift-harvest.d.ts +255 -0
  126. package/dist/core/ingestion/cfg/visitors/swift-harvest.js +679 -0
  127. package/dist/core/ingestion/cfg/visitors/swift.d.ts +116 -0
  128. package/dist/core/ingestion/cfg/visitors/swift.js +787 -0
  129. package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +149 -0
  130. package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1056 -0
  131. package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
  132. package/dist/core/ingestion/cfg/visitors/typescript.js +583 -0
  133. package/dist/core/ingestion/import-resolvers/utils.js +2 -0
  134. package/dist/core/ingestion/language-provider.d.ts +11 -0
  135. package/dist/core/ingestion/languages/c-cpp.js +6 -1
  136. package/dist/core/ingestion/languages/cobol.js +4 -0
  137. package/dist/core/ingestion/languages/cpp/arity-metadata.js +41 -2
  138. package/dist/core/ingestion/languages/cpp/captures.js +50 -1
  139. package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
  140. package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
  141. package/dist/core/ingestion/languages/cpp/header-scan.d.ts +1 -1
  142. package/dist/core/ingestion/languages/cpp/header-scan.js +2 -2
  143. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
  144. package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
  145. package/dist/core/ingestion/languages/cpp/query.js +23 -0
  146. package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
  147. package/dist/core/ingestion/languages/csharp.js +2 -0
  148. package/dist/core/ingestion/languages/dart.js +2 -0
  149. package/dist/core/ingestion/languages/go.js +2 -0
  150. package/dist/core/ingestion/languages/java.js +3 -0
  151. package/dist/core/ingestion/languages/kotlin/query.js +3 -2
  152. package/dist/core/ingestion/languages/kotlin.js +3 -0
  153. package/dist/core/ingestion/languages/php.js +2 -0
  154. package/dist/core/ingestion/languages/python.js +2 -0
  155. package/dist/core/ingestion/languages/ruby.js +2 -0
  156. package/dist/core/ingestion/languages/rust.js +2 -0
  157. package/dist/core/ingestion/languages/swift.js +2 -0
  158. package/dist/core/ingestion/languages/typescript.js +5 -0
  159. package/dist/core/ingestion/languages/vue.js +6 -0
  160. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
  161. package/dist/core/ingestion/method-extractors/generic.js +1 -0
  162. package/dist/core/ingestion/method-types.d.ts +2 -0
  163. package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
  164. package/dist/core/ingestion/model/symbol-table.js +1 -0
  165. package/dist/core/ingestion/mro-processor.js +109 -0
  166. package/dist/core/ingestion/parsing-processor.js +23 -0
  167. package/dist/core/ingestion/pipeline-phases/call-summaries.d.ts +26 -0
  168. package/dist/core/ingestion/pipeline-phases/call-summaries.js +46 -0
  169. package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
  170. package/dist/core/ingestion/pipeline-phases/index.js +2 -0
  171. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +0 -21
  172. package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
  173. package/dist/core/ingestion/pipeline-phases/routes.d.ts +10 -0
  174. package/dist/core/ingestion/pipeline-phases/routes.js +30 -1
  175. package/dist/core/ingestion/pipeline-phases/taint-summaries.d.ts +30 -0
  176. package/dist/core/ingestion/pipeline-phases/taint-summaries.js +81 -0
  177. package/dist/core/ingestion/pipeline.d.ts +92 -10
  178. package/dist/core/ingestion/pipeline.js +11 -2
  179. package/dist/core/ingestion/scope-extractor.js +12 -2
  180. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
  181. package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +75 -0
  182. package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +67 -0
  183. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -2
  184. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +14 -2
  185. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +6 -1
  186. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +13 -1
  187. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +9 -1
  188. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +28 -2
  189. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
  190. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
  191. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +6 -1
  192. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +174 -40
  193. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +24 -0
  194. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +276 -190
  195. package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
  196. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +75 -0
  197. package/dist/core/ingestion/scope-resolution/pipeline/run.js +349 -1
  198. package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
  199. package/dist/core/ingestion/taint/call-summary-codec.d.ts +75 -0
  200. package/dist/core/ingestion/taint/call-summary-codec.js +128 -0
  201. package/dist/core/ingestion/taint/call-summary-emit.d.ts +43 -0
  202. package/dist/core/ingestion/taint/call-summary-emit.js +70 -0
  203. package/dist/core/ingestion/taint/call-summary-harvest.d.ts +77 -0
  204. package/dist/core/ingestion/taint/call-summary-harvest.js +179 -0
  205. package/dist/core/ingestion/taint/call-summary-model.d.ts +47 -0
  206. package/dist/core/ingestion/taint/call-summary-model.js +25 -0
  207. package/dist/core/ingestion/taint/emit.d.ts +125 -0
  208. package/dist/core/ingestion/taint/emit.js +208 -0
  209. package/dist/core/ingestion/taint/interproc-emit.d.ts +50 -0
  210. package/dist/core/ingestion/taint/interproc-emit.js +88 -0
  211. package/dist/core/ingestion/taint/interproc-solver.d.ts +110 -0
  212. package/dist/core/ingestion/taint/interproc-solver.js +312 -0
  213. package/dist/core/ingestion/taint/match.d.ts +153 -0
  214. package/dist/core/ingestion/taint/match.js +278 -0
  215. package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
  216. package/dist/core/ingestion/taint/path-codec.js +190 -0
  217. package/dist/core/ingestion/taint/propagate.d.ts +216 -0
  218. package/dist/core/ingestion/taint/propagate.js +659 -0
  219. package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
  220. package/dist/core/ingestion/taint/site-safety.js +98 -0
  221. package/dist/core/ingestion/taint/source-sink-config.d.ts +107 -23
  222. package/dist/core/ingestion/taint/source-sink-config.js +35 -12
  223. package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
  224. package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
  225. package/dist/core/ingestion/taint/summary-harvest-driver.d.ts +80 -0
  226. package/dist/core/ingestion/taint/summary-harvest-driver.js +179 -0
  227. package/dist/core/ingestion/taint/summary-harvest.d.ts +89 -0
  228. package/dist/core/ingestion/taint/summary-harvest.js +537 -0
  229. package/dist/core/ingestion/taint/summary-model.d.ts +200 -0
  230. package/dist/core/ingestion/taint/summary-model.js +86 -0
  231. package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
  232. package/dist/core/ingestion/taint/typescript-model.js +102 -0
  233. package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
  234. package/dist/core/ingestion/utils/env.d.ts +7 -0
  235. package/dist/core/ingestion/utils/env.js +12 -0
  236. package/dist/core/ingestion/utils/method-props.js +1 -0
  237. package/dist/core/ingestion/workers/parse-worker.d.ts +13 -0
  238. package/dist/core/ingestion/workers/parse-worker.js +76 -17
  239. package/dist/core/ingestion/workers/worker-pool.d.ts +9 -40
  240. package/dist/core/ingestion/workers/worker-pool.js +15 -2
  241. package/dist/core/lbug/csv-generator.d.ts +51 -3
  242. package/dist/core/lbug/csv-generator.js +369 -255
  243. package/dist/core/lbug/lbug-adapter.d.ts +58 -18
  244. package/dist/core/lbug/lbug-adapter.js +346 -84
  245. package/dist/core/lbug/lbug-config.d.ts +19 -0
  246. package/dist/core/lbug/lbug-config.js +29 -0
  247. package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
  248. package/dist/core/lbug/pdg-emit-sink.js +358 -0
  249. package/dist/core/lbug/pool-adapter.d.ts +35 -0
  250. package/dist/core/lbug/pool-adapter.js +90 -1
  251. package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
  252. package/dist/core/lbug/rel-pair-routing.js +140 -0
  253. package/dist/core/lbug/schema.d.ts +2 -2
  254. package/dist/core/lbug/schema.js +3 -0
  255. package/dist/core/logger.d.ts +0 -5
  256. package/dist/core/run-analyze.d.ts +96 -0
  257. package/dist/core/run-analyze.js +207 -3
  258. package/dist/core/tree-sitter/parser-loader.js +5 -4
  259. package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
  260. package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
  261. package/dist/core/tree-sitter/vendored-grammars.js +57 -0
  262. package/dist/core/wiki/generator.js +3 -1
  263. package/dist/core/wiki/graph-queries.d.ts +6 -0
  264. package/dist/core/wiki/graph-queries.js +9 -1
  265. package/dist/mcp/http-transport.d.ts +134 -0
  266. package/dist/mcp/http-transport.js +503 -0
  267. package/dist/mcp/local/local-backend.d.ts +110 -24
  268. package/dist/mcp/local/local-backend.js +1225 -19
  269. package/dist/mcp/local/pdg-impact.d.ts +384 -0
  270. package/dist/mcp/local/pdg-impact.js +1972 -0
  271. package/dist/mcp/resources.js +13 -1
  272. package/dist/mcp/tools.d.ts +12 -0
  273. package/dist/mcp/tools.js +214 -7
  274. package/dist/server/analyze-launch.d.ts +29 -0
  275. package/dist/server/analyze-launch.js +137 -0
  276. package/dist/server/analyze-upload.d.ts +33 -0
  277. package/dist/server/analyze-upload.js +123 -0
  278. package/dist/server/analyze-worker.d.ts +17 -1
  279. package/dist/server/api.d.ts +17 -0
  280. package/dist/server/api.js +132 -168
  281. package/dist/server/git-clone.d.ts +43 -2
  282. package/dist/server/git-clone.js +211 -16
  283. package/dist/server/mcp-http.d.ts +5 -6
  284. package/dist/server/mcp-http.js +9 -82
  285. package/dist/server/middleware.d.ts +40 -0
  286. package/dist/server/middleware.js +92 -0
  287. package/dist/server/private-ip.d.ts +1 -0
  288. package/dist/server/private-ip.js +15 -0
  289. package/dist/server/upload-ingest.d.ts +56 -0
  290. package/dist/server/upload-ingest.js +276 -0
  291. package/dist/server/upload-paths.d.ts +37 -0
  292. package/dist/server/upload-paths.js +57 -0
  293. package/dist/server/upload-sweep.d.ts +20 -0
  294. package/dist/server/upload-sweep.js +57 -0
  295. package/dist/storage/git.js +5 -8
  296. package/dist/storage/parse-cache.d.ts +22 -1
  297. package/dist/storage/parse-cache.js +41 -10
  298. package/dist/storage/repo-manager.d.ts +121 -10
  299. package/dist/storage/repo-manager.js +43 -5
  300. package/dist/types/pipeline.d.ts +9 -0
  301. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
  302. package/hooks/claude/gitnexus-hook.cjs +110 -13
  303. package/hooks/claude/hook-db-lock-probe.cjs +513 -26
  304. package/package.json +8 -2
  305. package/scripts/assert-publish-grammar-coverage.cjs +31 -0
  306. package/scripts/build-tree-sitter-grammars.cjs +16 -10
  307. package/scripts/cross-platform-tests.ts +1 -0
  308. package/skills/gitnexus-debugging.md +16 -4
  309. package/skills/gitnexus-exploring.md +3 -3
  310. package/skills/gitnexus-guide.md +33 -0
  311. package/skills/gitnexus-pdg-query.md +89 -0
  312. package/skills/gitnexus-refactoring.md +1 -1
  313. package/skills/gitnexus-taint-analysis.md +178 -0
  314. package/vendor/tree-sitter-c/package.json +1 -1
  315. package/vendor/tree-sitter-dart/package.json +1 -1
  316. package/vendor/tree-sitter-kotlin/package.json +1 -1
  317. package/vendor/tree-sitter-proto/package.json +1 -1
  318. package/vendor/tree-sitter-swift/package.json +1 -1
  319. package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
  320. package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
  321. package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
  322. package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
  323. package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
  324. package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
  325. package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
  326. package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
  327. package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
  328. package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
  329. package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
  330. package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
  331. package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
  332. package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
  333. package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
  334. package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
  335. package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
  336. package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
  337. package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
  338. package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
  339. package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
  340. package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
  341. package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
  342. package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
  343. package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
  344. package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
  345. package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
  346. package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
  347. package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
  348. package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
  349. package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
  350. package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
  351. package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
  352. package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
  353. package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
  354. package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
  355. package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
  356. package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
  357. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
  358. package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
  359. package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
  360. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
  361. package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
  362. package/web/assets/index-BvYev1UJ.js +635 -0
  363. package/web/assets/index-_lgn7hs5.css +2 -0
  364. package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
  365. package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
  366. package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
  367. package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
  368. package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
  369. package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
  370. package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
  371. package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
  372. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
  373. package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
  374. package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
  375. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
  376. package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
  377. package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
  378. package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
  379. package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
  380. package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
  381. package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
  382. package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
  383. package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
  384. package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
  385. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
  386. package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
  387. package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
  388. package/web/index.html +13 -15
  389. package/scripts/materialize-vendor-grammars.cjs +0 -97
  390. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
  391. package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
  392. package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
  393. package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
  394. package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
  395. package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
  396. package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
  397. package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
  398. package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
  399. package/web/assets/chunk-CilyBKbf.js +0 -1
  400. package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
  401. package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
  402. package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
  403. package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
  404. package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
  405. package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
  406. package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
  407. package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
  408. package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
  409. package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
  410. package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
  411. package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
  412. package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
  413. package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
  414. package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
  415. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
  416. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
  417. package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
  418. package/web/assets/index-BKWA-m7o.css +0 -2
  419. package/web/assets/index-CG6q8eTs.js +0 -626
  420. package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
  421. package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
  422. package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
  423. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
  424. package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
  425. package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
  426. package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
  427. package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
  428. package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
  429. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
  430. /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
@@ -0,0 +1,679 @@
1
+ import { CallSiteFactAccumulator as FactAccumulator, finalizeChain } from './call-site-harvest.js';
2
+ /** Node types that own a nested CFG — their subtrees are opaque to harvesting. */
3
+ const NESTED_FUNCTION_TYPES = new Set([
4
+ 'function_declaration',
5
+ 'init_declaration',
6
+ 'deinit_declaration',
7
+ 'lambda_literal',
8
+ ]);
9
+ export class SwiftHarvester {
10
+ fnNode;
11
+ bindings = [];
12
+ /** Single function-scope name → binding index (v1: no block scope). */
13
+ table = new Map();
14
+ synthetic = new Map();
15
+ fnId;
16
+ /** >0 while walking a conditionally-evaluated subexpression — defs become may-defs. */
17
+ conditionalDepth = 0;
18
+ /**
19
+ * `call_expression` node id → binding indices its single-target result is
20
+ * assigned to (`let x = f()` / `x = g()` ⇒ `[x]`). Populated just before the
21
+ * value walk reaches the call (see {@link registerResultDefs}) and consumed by
22
+ * {@link visitCall}. Mirrors the Kotlin / Go / Python harvesters' map.
23
+ */
24
+ resultDefTargets = new Map();
25
+ constructor(fnNode) {
26
+ this.fnNode = fnNode;
27
+ this.fnId = fnNode.id;
28
+ this.declareParams(fnNode);
29
+ const body = this.bodyOf(fnNode);
30
+ if (body)
31
+ this.prescan(body);
32
+ }
33
+ /** The completed binding table — pass to `CfgBuilder.finish`. */
34
+ bindingTable() {
35
+ return this.bindings;
36
+ }
37
+ /**
38
+ * The function/closure body `statements` node. A `function_declaration` /
39
+ * `init_declaration` / `deinit_declaration` wraps it in a `function_body`; a
40
+ * `lambda_literal` carries the `statements` directly.
41
+ */
42
+ bodyOf(fnNode) {
43
+ const fb = fnNode.childForFieldName('body') ??
44
+ fnNode.namedChildren.find((c) => c.type === 'function_body');
45
+ if (fb && fb.type === 'function_body') {
46
+ return fb.namedChildren.find((c) => c.type === 'statements') ?? fb;
47
+ }
48
+ // lambda_literal — its `statements` is a direct named child.
49
+ return fnNode.namedChildren.find((c) => c.type === 'statements');
50
+ }
51
+ // ── phase 1: declaration pre-scan ────────────────────────────────────────
52
+ declare(nameNode, kind) {
53
+ const name = nameNode.text;
54
+ if (!name || name === '_' || this.table.has(name))
55
+ return;
56
+ this.table.set(name, this.bindings.length);
57
+ this.bindings.push({
58
+ name,
59
+ declLine: nameNode.startPosition.row + 1,
60
+ declColumn: nameNode.startPosition.column,
61
+ kind,
62
+ });
63
+ }
64
+ /** Declare every parameter binder of a fn / init / closure. */
65
+ declareParams(fnNode) {
66
+ for (const p of fnNode.namedChildren) {
67
+ if (p.type === 'parameter') {
68
+ const name = p.childForFieldName('name');
69
+ if (name && name.type === 'simple_identifier')
70
+ this.declare(name, 'param');
71
+ }
72
+ }
73
+ // Closure params live in lambda_function_type → lambda_function_type_parameters.
74
+ const lambdaType = fnNode.namedChildren.find((c) => c.type === 'lambda_function_type');
75
+ if (lambdaType)
76
+ this.declareClosureParams(lambdaType);
77
+ }
78
+ declareClosureParams(lambdaType) {
79
+ for (const params of lambdaType.namedChildren) {
80
+ if (params.type !== 'lambda_function_type_parameters')
81
+ continue;
82
+ for (const id of params.namedChildren) {
83
+ if (id.type === 'simple_identifier')
84
+ this.declare(id, 'param');
85
+ else if (id.type === 'lambda_parameter') {
86
+ const name = id.childForFieldName('name') ??
87
+ id.namedChildren.find((c) => c.type === 'simple_identifier');
88
+ if (name)
89
+ this.declare(name, 'param');
90
+ }
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Pre-scan the function body once, declaring every bound name. Recurses into
96
+ * compound expressions but NOT into nested `function_declaration` /
97
+ * `lambda_literal` bodies (opaque).
98
+ */
99
+ prescan(node) {
100
+ const t = node.type;
101
+ if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
102
+ return;
103
+ switch (t) {
104
+ case 'property_declaration':
105
+ // `let`/`var PAT = …` — declare every `name` pattern's leaves.
106
+ for (let i = 0; i < node.childCount; i++) {
107
+ if (node.fieldNameForChild(i) === 'name') {
108
+ const pat = node.child(i);
109
+ if (pat)
110
+ this.declarePattern(pat);
111
+ }
112
+ }
113
+ break;
114
+ case 'for_statement': {
115
+ const pat = node.childForFieldName('item');
116
+ if (pat)
117
+ this.declarePattern(pat);
118
+ break;
119
+ }
120
+ case 'catch_block': {
121
+ const err = node.childForFieldName('error');
122
+ if (err)
123
+ this.declarePattern(err);
124
+ break;
125
+ }
126
+ case 'switch_pattern': {
127
+ // `case let n` / `case (let a, let b)` / `case .some(let v)` — declare
128
+ // the value binding(s) so a body use resolves to a real local.
129
+ const pat = node.namedChildren.find((c) => c.type === 'pattern');
130
+ if (pat)
131
+ this.declarePattern(pat);
132
+ break;
133
+ }
134
+ default:
135
+ // Optional binding (`if let` / `while let` / `guard let`): a
136
+ // `value_binding_pattern` condition followed by a `bound_identifier`.
137
+ if (t === 'if_statement' || t === 'while_statement' || t === 'guard_statement') {
138
+ this.declareOptionalBindings(node);
139
+ }
140
+ break;
141
+ }
142
+ for (let i = 0; i < node.namedChildCount; i++) {
143
+ const c = node.namedChild(i);
144
+ if (c)
145
+ this.prescan(c);
146
+ }
147
+ }
148
+ /** Declare the bindings of each optional binding in a condition. */
149
+ declareOptionalBindings(node) {
150
+ for (let i = 0; i < node.childCount; i++) {
151
+ const child = node.child(i);
152
+ if (!child)
153
+ continue;
154
+ // `if/guard let v = e` — a direct `bound_identifier` field.
155
+ if (node.fieldNameForChild(i) === 'bound_identifier') {
156
+ this.declare(child, 'let');
157
+ }
158
+ else if (child.type === 'pattern') {
159
+ // `if/guard case PAT = e` (e.g. `case .some(let v)`): the binder is nested
160
+ // in a `pattern` condition child, not a direct `bound_identifier`, so it
161
+ // was missed and resolved to a synthetic global. declarePattern finds its
162
+ // bound leaves (#2206).
163
+ this.declarePattern(child);
164
+ }
165
+ }
166
+ }
167
+ /**
168
+ * Declare every `simple_identifier` leaf of a binding pattern. Handles the
169
+ * common Swift pattern shapes: a `bound_identifier` simple pattern and tuple
170
+ * destructuring (`(a, b)`), which nests `pattern` children. `_` (the wildcard)
171
+ * binds nothing.
172
+ */
173
+ declarePattern(pat) {
174
+ const bound = pat.childForFieldName?.('bound_identifier');
175
+ if (bound && bound.type === 'simple_identifier') {
176
+ this.declare(bound, 'let');
177
+ return;
178
+ }
179
+ if (pat.type === 'simple_identifier') {
180
+ this.declare(pat, 'let');
181
+ return;
182
+ }
183
+ // Tuple / nested pattern — recurse into child patterns / identifiers.
184
+ for (let i = 0; i < pat.namedChildCount; i++) {
185
+ const c = pat.namedChild(i);
186
+ if (!c)
187
+ continue;
188
+ if (c.type === 'pattern')
189
+ this.declarePattern(c);
190
+ else if (c.type === 'simple_identifier')
191
+ this.declare(c, 'let');
192
+ else if (c.type === 'value_binding_pattern')
193
+ continue;
194
+ else
195
+ this.declarePattern(c);
196
+ }
197
+ }
198
+ // ── phase 2: per-statement fact extraction ───────────────────────────────
199
+ /** Def/use facts for one statement (or construct-header expression) node. */
200
+ facts(node) {
201
+ const acc = new FactAccumulator(node.startPosition.row + 1);
202
+ this.walkValue(node, acc);
203
+ return acc.finish();
204
+ }
205
+ /** Facts for an expression whose WHOLE evaluation is conditional (guards/tests). */
206
+ factsConditional(node) {
207
+ const acc = new FactAccumulator(node.startPosition.row + 1);
208
+ this.conditional(() => this.walkValue(node, acc));
209
+ return acc.finish();
210
+ }
211
+ /**
212
+ * Def-ONLY facts for a value-position binding carrier (`let x = if … / switch …`,
213
+ * #2207): just the declared name pattern's leaves, attached to the continuation
214
+ * block the branch arms rejoin. The condition + arm-value USES are already
215
+ * harvested onto the branch's own blocks (visitIf / visitSwitch), so this must
216
+ * NOT re-walk the value — only the `name`-field pattern leaves are defs here.
217
+ */
218
+ bindingDefFacts(stmt) {
219
+ const acc = new FactAccumulator(stmt.startPosition.row + 1);
220
+ for (let i = 0; i < stmt.childCount; i++) {
221
+ if (stmt.fieldNameForChild(i) === 'name') {
222
+ const pat = stmt.child(i);
223
+ if (pat)
224
+ this.defPattern(pat, acc);
225
+ }
226
+ }
227
+ return acc.defCount() ? acc.finish() : undefined;
228
+ }
229
+ /**
230
+ * MAY-def facts for a `switch_pattern`'s value bindings (`case let n` /
231
+ * `case .some(let v)`). The binding only takes effect when the case matches,
232
+ * so it is a may-def on the dispatch block — propagated into the case body
233
+ * where the bound name is read.
234
+ */
235
+ switchPatternFacts(switchPattern) {
236
+ const acc = new FactAccumulator(switchPattern.startPosition.row + 1);
237
+ const pat = switchPattern.namedChildren.find((c) => c.type === 'pattern');
238
+ if (pat)
239
+ this.conditional(() => this.defPattern(pat, acc));
240
+ return acc.finish();
241
+ }
242
+ /**
243
+ * Facts for a `for item in COLLECTION` head: the loop pattern's leaves are
244
+ * defs, the iterated collection a use. The `where` guard (if any) is harvested
245
+ * conditionally.
246
+ */
247
+ forHeadFacts(stmt) {
248
+ const acc = new FactAccumulator(stmt.startPosition.row + 1);
249
+ const collection = stmt.childForFieldName('collection');
250
+ const item = stmt.childForFieldName('item');
251
+ if (collection)
252
+ this.walkValue(collection, acc);
253
+ if (item)
254
+ this.defPattern(item, acc);
255
+ const where = stmt.namedChildren.find((c) => c.type === 'where_clause');
256
+ if (where)
257
+ this.conditional(() => this.walkValue(where, acc));
258
+ return acc.finish();
259
+ }
260
+ /**
261
+ * Facts for an `if`/`while`/`guard` condition: optional bindings bind their
262
+ * pattern (a def — a may-def when `conditional`), and the condition expression
263
+ * children are uses. The construct's `condition` / `bound_identifier` fields are
264
+ * interleaved, so we walk all children and classify them.
265
+ */
266
+ conditionFacts(stmt, conditional) {
267
+ const acc = new FactAccumulator(stmt.startPosition.row + 1);
268
+ const run = () => {
269
+ for (let i = 0; i < stmt.childCount; i++) {
270
+ const field = stmt.fieldNameForChild(i);
271
+ const child = stmt.child(i);
272
+ if (!child)
273
+ continue;
274
+ if (field === 'bound_identifier')
275
+ this.def(child, acc);
276
+ else if (field === 'condition') {
277
+ // `value_binding_pattern` (`let`) and the `=` operator carry no uses.
278
+ if (child.type === 'value_binding_pattern')
279
+ continue;
280
+ if (!child.isNamed)
281
+ continue;
282
+ // `if/guard case PAT = e` (e.g. `case .some(let v)`): the `pattern` child
283
+ // BINDS — its leaves are defs (a may-def when conditional), not uses, so
284
+ // a tainted subject propagates to the binding (#2206). The matched
285
+ // subject and any other condition child are uses.
286
+ if (child.type === 'pattern')
287
+ this.defPattern(child, acc);
288
+ else
289
+ this.walkValue(child, acc);
290
+ }
291
+ }
292
+ };
293
+ if (conditional)
294
+ this.conditional(run);
295
+ else
296
+ run();
297
+ return acc.finish();
298
+ }
299
+ /** ENTRY-block facts for the parameters (defs only). */
300
+ paramFacts() {
301
+ const acc = new FactAccumulator(this.fnNode.startPosition.row + 1);
302
+ for (const p of this.fnNode.namedChildren) {
303
+ if (p.type === 'parameter') {
304
+ const name = p.childForFieldName('name');
305
+ if (name && name.type === 'simple_identifier')
306
+ this.def(name, acc);
307
+ }
308
+ }
309
+ const lambdaType = this.fnNode.namedChildren.find((c) => c.type === 'lambda_function_type');
310
+ if (lambdaType) {
311
+ for (const params of lambdaType.namedChildren) {
312
+ if (params.type !== 'lambda_function_type_parameters')
313
+ continue;
314
+ for (const id of params.namedChildren) {
315
+ if (id.type === 'simple_identifier')
316
+ this.def(id, acc);
317
+ else if (id.type === 'lambda_parameter') {
318
+ const name = id.childForFieldName('name') ??
319
+ id.namedChildren.find((c) => c.type === 'simple_identifier');
320
+ if (name)
321
+ this.def(name, acc);
322
+ }
323
+ }
324
+ }
325
+ }
326
+ return acc.defCount() ? acc.finish() : undefined;
327
+ }
328
+ /** Def fact for a `catch let e` error pattern — prepend to the handler entry block. */
329
+ catchErrorFacts(catchBlock) {
330
+ const err = catchBlock.childForFieldName('error');
331
+ if (!err)
332
+ return undefined;
333
+ const acc = new FactAccumulator(catchBlock.startPosition.row + 1);
334
+ this.defPattern(err, acc);
335
+ return acc.defCount() ? acc.finish() : undefined;
336
+ }
337
+ resolve(nameNode) {
338
+ const name = nameNode.text;
339
+ const idx = this.table.get(name);
340
+ if (idx !== undefined)
341
+ return idx;
342
+ let syn = this.synthetic.get(name);
343
+ if (syn === undefined) {
344
+ syn = this.bindings.length;
345
+ this.synthetic.set(name, syn);
346
+ this.bindings.push({ name, declLine: 0, declColumn: 0, kind: 'module', synthetic: true });
347
+ }
348
+ return syn;
349
+ }
350
+ def(nameNode, acc) {
351
+ if (nameNode.text === '_')
352
+ return; // blank target defines nothing
353
+ if (this.conditionalDepth > 0)
354
+ acc.addMayDef(this.resolve(nameNode));
355
+ else
356
+ acc.addDef(this.resolve(nameNode));
357
+ }
358
+ use(nameNode, acc) {
359
+ if (nameNode.text === '_')
360
+ return;
361
+ acc.addUse(this.resolve(nameNode));
362
+ }
363
+ /** Run `fn` with defs demoted to may-defs (conditionally-evaluated context). */
364
+ conditional(fn) {
365
+ this.conditionalDepth++;
366
+ try {
367
+ fn();
368
+ }
369
+ finally {
370
+ this.conditionalDepth--;
371
+ }
372
+ }
373
+ /**
374
+ * Def each `simple_identifier` leaf of a binding pattern (the def-position
375
+ * analogue of {@link declarePattern}). Tuple destructuring recurses; `_` binds
376
+ * nothing.
377
+ */
378
+ defPattern(pat, acc) {
379
+ const bound = pat.childForFieldName?.('bound_identifier');
380
+ if (bound && bound.type === 'simple_identifier') {
381
+ this.def(bound, acc);
382
+ return;
383
+ }
384
+ if (pat.type === 'simple_identifier') {
385
+ this.def(pat, acc);
386
+ return;
387
+ }
388
+ for (let i = 0; i < pat.namedChildCount; i++) {
389
+ const c = pat.namedChild(i);
390
+ if (!c)
391
+ continue;
392
+ if (c.type === 'pattern')
393
+ this.defPattern(c, acc);
394
+ else if (c.type === 'simple_identifier')
395
+ this.def(c, acc);
396
+ else if (c.type === 'value_binding_pattern')
397
+ continue;
398
+ else
399
+ this.defPattern(c, acc);
400
+ }
401
+ }
402
+ /** Value-position walk: collect uses; route def positions to the pattern handler. */
403
+ walkValue(node, acc) {
404
+ const t = node.type;
405
+ if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
406
+ return; // opaque
407
+ switch (t) {
408
+ case 'simple_identifier':
409
+ this.use(node, acc);
410
+ return;
411
+ case 'property_declaration': {
412
+ // Walk each `value` for uses, then def each `name` pattern's leaves.
413
+ const names = [];
414
+ const values = [];
415
+ for (let i = 0; i < node.childCount; i++) {
416
+ const field = node.fieldNameForChild(i);
417
+ const child = node.child(i);
418
+ if (!child)
419
+ continue;
420
+ if (field === 'value' || field === 'computed_value')
421
+ values.push(child);
422
+ else if (field === 'name')
423
+ names.push(child);
424
+ }
425
+ // Register result-defs BEFORE the value walk so the call the walk reaches
426
+ // carries them — single-name `let x = f()` only (a destructuring or
427
+ // multi-binder `let (a, b) = …` / `let p = 1, q = 2` attaches nothing).
428
+ const single = this.singlePatternBinder(names);
429
+ if (single && values.length === 1)
430
+ this.registerResultDefs(values[0], [single]);
431
+ for (const value of values)
432
+ this.walkValue(value, acc);
433
+ for (const pat of names)
434
+ this.defPattern(pat, acc);
435
+ return;
436
+ }
437
+ case 'assignment': {
438
+ const target = node.childForFieldName('target');
439
+ const result = node.childForFieldName('result');
440
+ const op = node.childForFieldName('operator')?.text ?? '=';
441
+ const lv = target ? this.unwrapAssignable(target) : undefined;
442
+ const scalar = lv && lv.type === 'simple_identifier' ? lv : undefined;
443
+ // A plain `x = <call>` attaches `resultDefs: [x]`; a compound `+=` does
444
+ // not (the prior value flows in too).
445
+ if (scalar && op === '=' && result)
446
+ this.registerResultDefs(result, [scalar]);
447
+ if (result)
448
+ this.walkValue(result, acc);
449
+ if (lv) {
450
+ if (scalar) {
451
+ this.def(scalar, acc);
452
+ if (op !== '=')
453
+ this.use(scalar, acc); // compound assign reads too
454
+ }
455
+ else {
456
+ // `self.x = …`, `a[i] = …` — root is a use only (not a scalar def).
457
+ this.walkValue(lv, acc);
458
+ }
459
+ }
460
+ return;
461
+ }
462
+ case 'call_expression':
463
+ // A Swift call (`foo(a)`, `obj.method(x)`, `a.b.c()`, `Foo(...)`). Records
464
+ // a taint site (callee path, receiver, per-arg occurrences, result defs)
465
+ // while reproducing the uses the old default descent recorded. Swift has
466
+ // no `new` — every site is `kind: 'call'`.
467
+ this.visitCall(node, acc);
468
+ return;
469
+ case 'navigation_expression': {
470
+ // `a.b` value read — the chain-root identifier is a use plus at most one
471
+ // member-read site (the innermost access); the suffix name is not a scalar
472
+ // binding. Mirrors the Kotlin / Go value-position member-read semantics.
473
+ this.walkChain(node, acc, false);
474
+ return;
475
+ }
476
+ case 'try_expression': {
477
+ // `try expr` / `try? expr` / `try! expr` — the wrapped expression's uses.
478
+ const expr = node.childForFieldName('expr');
479
+ if (expr)
480
+ this.walkValue(expr, acc);
481
+ else
482
+ for (let i = 0; i < node.namedChildCount; i++) {
483
+ const c = node.namedChild(i);
484
+ if (c && c.type !== 'try_operator')
485
+ this.walkValue(c, acc);
486
+ }
487
+ return;
488
+ }
489
+ case 'conjunction_expression':
490
+ case 'disjunction_expression': {
491
+ // `a && b` / `a || b` — the right operand is conditionally evaluated.
492
+ const lhs = node.childForFieldName('lhs');
493
+ const rhs = node.childForFieldName('rhs');
494
+ if (lhs)
495
+ this.walkValue(lhs, acc);
496
+ else if (node.namedChildCount > 0)
497
+ this.walkValue(node.namedChild(0), acc);
498
+ if (rhs)
499
+ this.conditional(() => this.walkValue(rhs, acc));
500
+ else if (node.namedChildCount > 1) {
501
+ this.conditional(() => this.walkValue(node.namedChild(node.namedChildCount - 1), acc));
502
+ }
503
+ return;
504
+ }
505
+ case 'value_binding_pattern':
506
+ case 'type_identifier':
507
+ case 'user_type':
508
+ // Binding keyword / type position — no scalar value uses.
509
+ return;
510
+ default:
511
+ for (let i = 0; i < node.namedChildCount; i++) {
512
+ const c = node.namedChild(i);
513
+ if (c)
514
+ this.walkValue(c, acc);
515
+ }
516
+ }
517
+ }
518
+ /** Strip a `directly_assignable_expression` wrapper around an lvalue. */
519
+ unwrapAssignable(node) {
520
+ let n = node;
521
+ let hops = 4;
522
+ while (n.type === 'directly_assignable_expression' && hops-- > 0) {
523
+ const inner = n.namedChild(0);
524
+ if (!inner)
525
+ break;
526
+ n = inner;
527
+ }
528
+ return n;
529
+ }
530
+ // ── taint-site harvest ───────────────────────────────────────────────────
531
+ /**
532
+ * The sole `bound_identifier` binder of a single `name` pattern, or undefined
533
+ * when there are multiple `name` patterns or the pattern is a tuple / wildcard
534
+ * destructuring (`let (a, b) = …`). Used to gate single-target result-defs.
535
+ */
536
+ singlePatternBinder(names) {
537
+ if (names.length !== 1)
538
+ return undefined;
539
+ const pat = names[0];
540
+ const bound = pat.childForFieldName?.('bound_identifier');
541
+ if (bound && bound.type === 'simple_identifier' && bound.text !== '_')
542
+ return bound;
543
+ if (pat.type === 'simple_identifier' && pat.text !== '_')
544
+ return pat;
545
+ return undefined;
546
+ }
547
+ /**
548
+ * When `value`'s root (after unwrapping) is a `call_expression`, remember that
549
+ * call site should carry `resultDefs` — the binding indices of `targets`
550
+ * (def-position identifiers). Consumed by {@link visitCall} once the value walk
551
+ * reaches the node. Single-target only; the blank target (`_`) binds nothing.
552
+ */
553
+ registerResultDefs(value, targets) {
554
+ const root = this.unwrapAssignable(value);
555
+ if (root.type !== 'call_expression')
556
+ return;
557
+ const defs = [];
558
+ for (const target of targets) {
559
+ if (target.type !== 'simple_identifier' || target.text === '_')
560
+ continue;
561
+ defs.push(this.resolve(target));
562
+ }
563
+ if (defs.length > 0)
564
+ this.resultDefTargets.set(root.id, defs);
565
+ }
566
+ /**
567
+ * The callee node of a `call_expression` — the first named child that is NOT
568
+ * the trailing `call_suffix` (a bare `simple_identifier` for a free / init
569
+ * call, or a `navigation_expression` for a member / chained call).
570
+ */
571
+ calleeOf(call) {
572
+ for (let i = 0; i < call.namedChildCount; i++) {
573
+ const c = call.namedChild(i);
574
+ if (c && c.type !== 'call_suffix')
575
+ return c;
576
+ }
577
+ return undefined;
578
+ }
579
+ /**
580
+ * Open + populate a call site for a Swift `call_expression`. `node` IS the
581
+ * `call_expression` — the SAME node the scope query anchors `@reference.call.*`
582
+ * on (its `atRange`), so the resolved-id join lands by exact position (see file
583
+ * header ANCHOR ALIGNMENT). Swift has no `new`, so every site is `kind: 'call'`.
584
+ */
585
+ visitCall(node, acc) {
586
+ const calleeNode = this.calleeOf(node);
587
+ const siteIdx = acc.openCallSite('call', [
588
+ node.startPosition.row + 1,
589
+ node.startPosition.column,
590
+ ]);
591
+ acc.pushFrame(siteIdx);
592
+ if (calleeNode) {
593
+ const callee = this.unwrapAssignable(calleeNode);
594
+ if (callee.type === 'simple_identifier') {
595
+ // A bare free / init call — the callee NAME is a statement-level use but
596
+ // NOT a value occurrence in any enclosing argument.
597
+ if (callee.text !== '_')
598
+ acc.addUseWithoutOccurrence(this.resolve(callee));
599
+ acc.setSiteCallee(siteIdx, callee.text);
600
+ }
601
+ else if (callee.type === 'navigation_expression') {
602
+ // skipFinalRead: the final `.name` IS the callee, carried by the path.
603
+ const chain = this.walkChain(callee, acc, true);
604
+ if (chain.path !== undefined)
605
+ acc.setSiteCallee(siteIdx, chain.path);
606
+ if (chain.rootIdx !== undefined)
607
+ acc.setSiteReceiver(siteIdx, chain.rootIdx);
608
+ }
609
+ else {
610
+ // Call-rooted chains (`f()()`), parenthesized callables, `self.x`-rooted —
611
+ // the walk still records uses and nested sites; no static callee path.
612
+ this.walkValue(callee, acc);
613
+ }
614
+ }
615
+ const resultDefs = this.resultDefTargets.get(node.id);
616
+ if (resultDefs !== undefined)
617
+ acc.setSiteResultDefs(siteIdx, resultDefs);
618
+ const suffix = node.namedChildren.find((c) => c.type === 'call_suffix');
619
+ if (suffix)
620
+ this.walkArguments(suffix, acc);
621
+ acc.popFrame();
622
+ }
623
+ /**
624
+ * Walk a `call_suffix`'s `value_arguments`, tagging each positional / labeled
625
+ * argument's occurrence position. A trailing closure (`lambda_literal`) is a
626
+ * nested function body — opaque (excluded by {@link NESTED_FUNCTION_TYPES}), so
627
+ * it is not an argument occurrence here.
628
+ */
629
+ walkArguments(suffix, acc) {
630
+ const args = suffix.namedChildren.find((c) => c.type === 'value_arguments');
631
+ if (!args)
632
+ return;
633
+ let pos = 0;
634
+ for (let i = 0; i < args.namedChildCount; i++) {
635
+ const arg = args.namedChild(i);
636
+ if (!arg || arg.type !== 'value_argument')
637
+ continue;
638
+ acc.setFrameArg(pos);
639
+ // A labeled arg (`name: value`) records only the VALUE occurrence — the
640
+ // `value_argument_label` is dropped. An `&inout` value walks its `target`
641
+ // identifier for the use. Swift has no call-site spread operator.
642
+ const value = arg.childForFieldName('value');
643
+ if (value)
644
+ this.walkValue(value, acc);
645
+ pos++;
646
+ }
647
+ }
648
+ /**
649
+ * `navigation_expression` chain walk shared by value position and callee
650
+ * position. Records the chain-root identifier as a use plus at most ONE
651
+ * member-read site — the INNERMOST access — when the root is an identifier;
652
+ * `skipFinalRead` suppresses it when that access is the callee (carried by the
653
+ * dotted path instead). Mirrors the Kotlin / Go / Python harvesters' walkChain.
654
+ * A non-identifier root (`self`/literal/call) launders no static path/receiver.
655
+ */
656
+ walkChain(node, acc, skipFinalRead) {
657
+ const accesses = [];
658
+ let cur = this.unwrapAssignable(node);
659
+ for (;;) {
660
+ if (cur.type === 'navigation_expression') {
661
+ const suffix = cur.childForFieldName('suffix');
662
+ const name = suffix?.childForFieldName('suffix');
663
+ accesses.unshift(name?.text ?? '');
664
+ const operand = cur.childForFieldName('target');
665
+ if (!operand)
666
+ break;
667
+ cur = this.unwrapAssignable(operand);
668
+ }
669
+ else {
670
+ break;
671
+ }
672
+ }
673
+ // The shared terminal: root-use record + innermost member-read + path-join.
674
+ return finalizeChain(acc, cur, accesses, skipFinalRead, (t) => t === 'simple_identifier', {
675
+ resolve: (n) => this.resolve(n),
676
+ walkRoot: (n) => this.walkValue(n, acc),
677
+ });
678
+ }
679
+ }