optave-codegraph 3.13.0

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 (1672) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +984 -0
  3. package/dist/ast-analysis/engine.d.ts +19 -0
  4. package/dist/ast-analysis/engine.d.ts.map +1 -0
  5. package/dist/ast-analysis/engine.js +660 -0
  6. package/dist/ast-analysis/engine.js.map +1 -0
  7. package/dist/ast-analysis/metrics.d.ts +34 -0
  8. package/dist/ast-analysis/metrics.d.ts.map +1 -0
  9. package/dist/ast-analysis/metrics.js +123 -0
  10. package/dist/ast-analysis/metrics.js.map +1 -0
  11. package/dist/ast-analysis/rules/b2.d.ts +7 -0
  12. package/dist/ast-analysis/rules/b2.d.ts.map +1 -0
  13. package/dist/ast-analysis/rules/b2.js +240 -0
  14. package/dist/ast-analysis/rules/b2.js.map +1 -0
  15. package/dist/ast-analysis/rules/b3.d.ts +6 -0
  16. package/dist/ast-analysis/rules/b3.d.ts.map +1 -0
  17. package/dist/ast-analysis/rules/b3.js +105 -0
  18. package/dist/ast-analysis/rules/b3.js.map +1 -0
  19. package/dist/ast-analysis/rules/b4.d.ts +9 -0
  20. package/dist/ast-analysis/rules/b4.d.ts.map +1 -0
  21. package/dist/ast-analysis/rules/b4.js +361 -0
  22. package/dist/ast-analysis/rules/b4.js.map +1 -0
  23. package/dist/ast-analysis/rules/b5.d.ts +4 -0
  24. package/dist/ast-analysis/rules/b5.d.ts.map +1 -0
  25. package/dist/ast-analysis/rules/b5.js +52 -0
  26. package/dist/ast-analysis/rules/b5.js.map +1 -0
  27. package/dist/ast-analysis/rules/c.d.ts +4 -0
  28. package/dist/ast-analysis/rules/c.d.ts.map +1 -0
  29. package/dist/ast-analysis/rules/c.js +143 -0
  30. package/dist/ast-analysis/rules/c.js.map +1 -0
  31. package/dist/ast-analysis/rules/csharp.d.ts +7 -0
  32. package/dist/ast-analysis/rules/csharp.d.ts.map +1 -0
  33. package/dist/ast-analysis/rules/csharp.js +196 -0
  34. package/dist/ast-analysis/rules/csharp.js.map +1 -0
  35. package/dist/ast-analysis/rules/go.d.ts +7 -0
  36. package/dist/ast-analysis/rules/go.d.ts.map +1 -0
  37. package/dist/ast-analysis/rules/go.js +173 -0
  38. package/dist/ast-analysis/rules/go.js.map +1 -0
  39. package/dist/ast-analysis/rules/index.d.ts +13 -0
  40. package/dist/ast-analysis/rules/index.d.ts.map +1 -0
  41. package/dist/ast-analysis/rules/index.js +325 -0
  42. package/dist/ast-analysis/rules/index.js.map +1 -0
  43. package/dist/ast-analysis/rules/java.d.ts +7 -0
  44. package/dist/ast-analysis/rules/java.d.ts.map +1 -0
  45. package/dist/ast-analysis/rules/java.js +167 -0
  46. package/dist/ast-analysis/rules/java.js.map +1 -0
  47. package/dist/ast-analysis/rules/javascript.d.ts +7 -0
  48. package/dist/ast-analysis/rules/javascript.d.ts.map +1 -0
  49. package/dist/ast-analysis/rules/javascript.js +233 -0
  50. package/dist/ast-analysis/rules/javascript.js.map +1 -0
  51. package/dist/ast-analysis/rules/php.d.ts +7 -0
  52. package/dist/ast-analysis/rules/php.d.ts.map +1 -0
  53. package/dist/ast-analysis/rules/php.js +212 -0
  54. package/dist/ast-analysis/rules/php.js.map +1 -0
  55. package/dist/ast-analysis/rules/python.d.ts +7 -0
  56. package/dist/ast-analysis/rules/python.d.ts.map +1 -0
  57. package/dist/ast-analysis/rules/python.js +189 -0
  58. package/dist/ast-analysis/rules/python.js.map +1 -0
  59. package/dist/ast-analysis/rules/ruby.d.ts +7 -0
  60. package/dist/ast-analysis/rules/ruby.d.ts.map +1 -0
  61. package/dist/ast-analysis/rules/ruby.js +193 -0
  62. package/dist/ast-analysis/rules/ruby.js.map +1 -0
  63. package/dist/ast-analysis/rules/rust.d.ts +7 -0
  64. package/dist/ast-analysis/rules/rust.d.ts.map +1 -0
  65. package/dist/ast-analysis/rules/rust.js +166 -0
  66. package/dist/ast-analysis/rules/rust.js.map +1 -0
  67. package/dist/ast-analysis/shared.d.ts +12 -0
  68. package/dist/ast-analysis/shared.d.ts.map +1 -0
  69. package/dist/ast-analysis/shared.js +166 -0
  70. package/dist/ast-analysis/shared.js.map +1 -0
  71. package/dist/ast-analysis/visitor-utils.d.ts +70 -0
  72. package/dist/ast-analysis/visitor-utils.d.ts.map +1 -0
  73. package/dist/ast-analysis/visitor-utils.js +235 -0
  74. package/dist/ast-analysis/visitor-utils.js.map +1 -0
  75. package/dist/ast-analysis/visitor.d.ts +27 -0
  76. package/dist/ast-analysis/visitor.d.ts.map +1 -0
  77. package/dist/ast-analysis/visitor.js +178 -0
  78. package/dist/ast-analysis/visitor.js.map +1 -0
  79. package/dist/ast-analysis/visitors/ast-store-visitor.d.ts +4 -0
  80. package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -0
  81. package/dist/ast-analysis/visitors/ast-store-visitor.js +288 -0
  82. package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -0
  83. package/dist/ast-analysis/visitors/cfg-conditionals.d.ts +5 -0
  84. package/dist/ast-analysis/visitors/cfg-conditionals.d.ts.map +1 -0
  85. package/dist/ast-analysis/visitors/cfg-conditionals.js +166 -0
  86. package/dist/ast-analysis/visitors/cfg-conditionals.js.map +1 -0
  87. package/dist/ast-analysis/visitors/cfg-loops.d.ts +7 -0
  88. package/dist/ast-analysis/visitors/cfg-loops.d.ts.map +1 -0
  89. package/dist/ast-analysis/visitors/cfg-loops.js +73 -0
  90. package/dist/ast-analysis/visitors/cfg-loops.js.map +1 -0
  91. package/dist/ast-analysis/visitors/cfg-shared.d.ts +56 -0
  92. package/dist/ast-analysis/visitors/cfg-shared.d.ts.map +1 -0
  93. package/dist/ast-analysis/visitors/cfg-shared.js +107 -0
  94. package/dist/ast-analysis/visitors/cfg-shared.js.map +1 -0
  95. package/dist/ast-analysis/visitors/cfg-try-catch.d.ts +4 -0
  96. package/dist/ast-analysis/visitors/cfg-try-catch.d.ts.map +1 -0
  97. package/dist/ast-analysis/visitors/cfg-try-catch.js +100 -0
  98. package/dist/ast-analysis/visitors/cfg-try-catch.js.map +1 -0
  99. package/dist/ast-analysis/visitors/cfg-visitor.d.ts +5 -0
  100. package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -0
  101. package/dist/ast-analysis/visitors/cfg-visitor.js +231 -0
  102. package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -0
  103. package/dist/ast-analysis/visitors/complexity-visitor.d.ts +8 -0
  104. package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -0
  105. package/dist/ast-analysis/visitors/complexity-visitor.js +233 -0
  106. package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -0
  107. package/dist/ast-analysis/visitors/dataflow-visitor.d.ts +5 -0
  108. package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -0
  109. package/dist/ast-analysis/visitors/dataflow-visitor.js +378 -0
  110. package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -0
  111. package/dist/cli/commands/ast.d.ts +3 -0
  112. package/dist/cli/commands/ast.d.ts.map +1 -0
  113. package/dist/cli/commands/ast.js +23 -0
  114. package/dist/cli/commands/ast.js.map +1 -0
  115. package/dist/cli/commands/audit.d.ts +3 -0
  116. package/dist/cli/commands/audit.d.ts.map +1 -0
  117. package/dist/cli/commands/audit.js +47 -0
  118. package/dist/cli/commands/audit.js.map +1 -0
  119. package/dist/cli/commands/batch.d.ts +3 -0
  120. package/dist/cli/commands/batch.d.ts.map +1 -0
  121. package/dist/cli/commands/batch.js +66 -0
  122. package/dist/cli/commands/batch.js.map +1 -0
  123. package/dist/cli/commands/branch-compare.d.ts +3 -0
  124. package/dist/cli/commands/branch-compare.d.ts.map +1 -0
  125. package/dist/cli/commands/branch-compare.js +26 -0
  126. package/dist/cli/commands/branch-compare.js.map +1 -0
  127. package/dist/cli/commands/brief.d.ts +3 -0
  128. package/dist/cli/commands/brief.d.ts.map +1 -0
  129. package/dist/cli/commands/brief.js +12 -0
  130. package/dist/cli/commands/brief.js.map +1 -0
  131. package/dist/cli/commands/build.d.ts +3 -0
  132. package/dist/cli/commands/build.d.ts.map +1 -0
  133. package/dist/cli/commands/build.js +33 -0
  134. package/dist/cli/commands/build.js.map +1 -0
  135. package/dist/cli/commands/cfg.d.ts +3 -0
  136. package/dist/cli/commands/cfg.d.ts.map +1 -0
  137. package/dist/cli/commands/cfg.js +27 -0
  138. package/dist/cli/commands/cfg.js.map +1 -0
  139. package/dist/cli/commands/check.d.ts +3 -0
  140. package/dist/cli/commands/check.d.ts.map +1 -0
  141. package/dist/cli/commands/check.js +65 -0
  142. package/dist/cli/commands/check.js.map +1 -0
  143. package/dist/cli/commands/children.d.ts +3 -0
  144. package/dist/cli/commands/children.d.ts.map +1 -0
  145. package/dist/cli/commands/children.js +33 -0
  146. package/dist/cli/commands/children.js.map +1 -0
  147. package/dist/cli/commands/co-change.d.ts +3 -0
  148. package/dist/cli/commands/co-change.d.ts.map +1 -0
  149. package/dist/cli/commands/co-change.js +66 -0
  150. package/dist/cli/commands/co-change.js.map +1 -0
  151. package/dist/cli/commands/communities.d.ts +3 -0
  152. package/dist/cli/commands/communities.d.ts.map +1 -0
  153. package/dist/cli/commands/communities.js +20 -0
  154. package/dist/cli/commands/communities.js.map +1 -0
  155. package/dist/cli/commands/complexity.d.ts +3 -0
  156. package/dist/cli/commands/complexity.d.ts.map +1 -0
  157. package/dist/cli/commands/complexity.js +47 -0
  158. package/dist/cli/commands/complexity.js.map +1 -0
  159. package/dist/cli/commands/config.d.ts +3 -0
  160. package/dist/cli/commands/config.d.ts.map +1 -0
  161. package/dist/cli/commands/config.js +275 -0
  162. package/dist/cli/commands/config.js.map +1 -0
  163. package/dist/cli/commands/context.d.ts +3 -0
  164. package/dist/cli/commands/context.d.ts.map +1 -0
  165. package/dist/cli/commands/context.js +35 -0
  166. package/dist/cli/commands/context.js.map +1 -0
  167. package/dist/cli/commands/cycles.d.ts +3 -0
  168. package/dist/cli/commands/cycles.d.ts.map +1 -0
  169. package/dist/cli/commands/cycles.js +33 -0
  170. package/dist/cli/commands/cycles.js.map +1 -0
  171. package/dist/cli/commands/dataflow.d.ts +3 -0
  172. package/dist/cli/commands/dataflow.d.ts.map +1 -0
  173. package/dist/cli/commands/dataflow.js +29 -0
  174. package/dist/cli/commands/dataflow.js.map +1 -0
  175. package/dist/cli/commands/deps.d.ts +3 -0
  176. package/dist/cli/commands/deps.d.ts.map +1 -0
  177. package/dist/cli/commands/deps.js +18 -0
  178. package/dist/cli/commands/deps.js.map +1 -0
  179. package/dist/cli/commands/diff-impact.d.ts +3 -0
  180. package/dist/cli/commands/diff-impact.d.ts.map +1 -0
  181. package/dist/cli/commands/diff-impact.js +29 -0
  182. package/dist/cli/commands/diff-impact.js.map +1 -0
  183. package/dist/cli/commands/embed.d.ts +3 -0
  184. package/dist/cli/commands/embed.d.ts.map +1 -0
  185. package/dist/cli/commands/embed.js +75 -0
  186. package/dist/cli/commands/embed.js.map +1 -0
  187. package/dist/cli/commands/export.d.ts +3 -0
  188. package/dist/cli/commands/export.d.ts.map +1 -0
  189. package/dist/cli/commands/export.js +72 -0
  190. package/dist/cli/commands/export.js.map +1 -0
  191. package/dist/cli/commands/exports.d.ts +3 -0
  192. package/dist/cli/commands/exports.d.ts.map +1 -0
  193. package/dist/cli/commands/exports.js +14 -0
  194. package/dist/cli/commands/exports.js.map +1 -0
  195. package/dist/cli/commands/flow.d.ts +3 -0
  196. package/dist/cli/commands/flow.d.ts.map +1 -0
  197. package/dist/cli/commands/flow.js +32 -0
  198. package/dist/cli/commands/flow.js.map +1 -0
  199. package/dist/cli/commands/fn-impact.d.ts +3 -0
  200. package/dist/cli/commands/fn-impact.d.ts.map +1 -0
  201. package/dist/cli/commands/fn-impact.js +33 -0
  202. package/dist/cli/commands/fn-impact.js.map +1 -0
  203. package/dist/cli/commands/impact.d.ts +3 -0
  204. package/dist/cli/commands/impact.d.ts.map +1 -0
  205. package/dist/cli/commands/impact.js +12 -0
  206. package/dist/cli/commands/impact.js.map +1 -0
  207. package/dist/cli/commands/implementations.d.ts +3 -0
  208. package/dist/cli/commands/implementations.d.ts.map +1 -0
  209. package/dist/cli/commands/implementations.js +29 -0
  210. package/dist/cli/commands/implementations.js.map +1 -0
  211. package/dist/cli/commands/info.d.ts +3 -0
  212. package/dist/cli/commands/info.d.ts.map +1 -0
  213. package/dist/cli/commands/info.js +67 -0
  214. package/dist/cli/commands/info.js.map +1 -0
  215. package/dist/cli/commands/interfaces.d.ts +3 -0
  216. package/dist/cli/commands/interfaces.d.ts.map +1 -0
  217. package/dist/cli/commands/interfaces.js +29 -0
  218. package/dist/cli/commands/interfaces.js.map +1 -0
  219. package/dist/cli/commands/map.d.ts +3 -0
  220. package/dist/cli/commands/map.d.ts.map +1 -0
  221. package/dist/cli/commands/map.js +19 -0
  222. package/dist/cli/commands/map.js.map +1 -0
  223. package/dist/cli/commands/mcp.d.ts +3 -0
  224. package/dist/cli/commands/mcp.d.ts.map +1 -0
  225. package/dist/cli/commands/mcp.js +18 -0
  226. package/dist/cli/commands/mcp.js.map +1 -0
  227. package/dist/cli/commands/models.d.ts +3 -0
  228. package/dist/cli/commands/models.d.ts.map +1 -0
  229. package/dist/cli/commands/models.js +19 -0
  230. package/dist/cli/commands/models.js.map +1 -0
  231. package/dist/cli/commands/owners.d.ts +3 -0
  232. package/dist/cli/commands/owners.d.ts.map +1 -0
  233. package/dist/cli/commands/owners.js +27 -0
  234. package/dist/cli/commands/owners.js.map +1 -0
  235. package/dist/cli/commands/path.d.ts +3 -0
  236. package/dist/cli/commands/path.d.ts.map +1 -0
  237. package/dist/cli/commands/path.js +41 -0
  238. package/dist/cli/commands/path.js.map +1 -0
  239. package/dist/cli/commands/plot.d.ts +3 -0
  240. package/dist/cli/commands/plot.d.ts.map +1 -0
  241. package/dist/cli/commands/plot.js +96 -0
  242. package/dist/cli/commands/plot.js.map +1 -0
  243. package/dist/cli/commands/query.d.ts +3 -0
  244. package/dist/cli/commands/query.d.ts.map +1 -0
  245. package/dist/cli/commands/query.js +51 -0
  246. package/dist/cli/commands/query.js.map +1 -0
  247. package/dist/cli/commands/registry.d.ts +3 -0
  248. package/dist/cli/commands/registry.d.ts.map +1 -0
  249. package/dist/cli/commands/registry.js +95 -0
  250. package/dist/cli/commands/registry.js.map +1 -0
  251. package/dist/cli/commands/roles.d.ts +3 -0
  252. package/dist/cli/commands/roles.d.ts.map +1 -0
  253. package/dist/cli/commands/roles.js +36 -0
  254. package/dist/cli/commands/roles.js.map +1 -0
  255. package/dist/cli/commands/search.d.ts +3 -0
  256. package/dist/cli/commands/search.d.ts.map +1 -0
  257. package/dist/cli/commands/search.js +43 -0
  258. package/dist/cli/commands/search.js.map +1 -0
  259. package/dist/cli/commands/sequence.d.ts +3 -0
  260. package/dist/cli/commands/sequence.d.ts.map +1 -0
  261. package/dist/cli/commands/sequence.js +29 -0
  262. package/dist/cli/commands/sequence.js.map +1 -0
  263. package/dist/cli/commands/snapshot.d.ts +3 -0
  264. package/dist/cli/commands/snapshot.d.ts.map +1 -0
  265. package/dist/cli/commands/snapshot.js +61 -0
  266. package/dist/cli/commands/snapshot.js.map +1 -0
  267. package/dist/cli/commands/stats.d.ts +3 -0
  268. package/dist/cli/commands/stats.d.ts.map +1 -0
  269. package/dist/cli/commands/stats.js +15 -0
  270. package/dist/cli/commands/stats.js.map +1 -0
  271. package/dist/cli/commands/structure.d.ts +3 -0
  272. package/dist/cli/commands/structure.d.ts.map +1 -0
  273. package/dist/cli/commands/structure.js +50 -0
  274. package/dist/cli/commands/structure.js.map +1 -0
  275. package/dist/cli/commands/triage.d.ts +3 -0
  276. package/dist/cli/commands/triage.d.ts.map +1 -0
  277. package/dist/cli/commands/triage.js +89 -0
  278. package/dist/cli/commands/triage.js.map +1 -0
  279. package/dist/cli/commands/watch.d.ts +3 -0
  280. package/dist/cli/commands/watch.d.ts.map +1 -0
  281. package/dist/cli/commands/watch.js +28 -0
  282. package/dist/cli/commands/watch.js.map +1 -0
  283. package/dist/cli/commands/where.d.ts +3 -0
  284. package/dist/cli/commands/where.d.ts.map +1 -0
  285. package/dist/cli/commands/where.js +20 -0
  286. package/dist/cli/commands/where.js.map +1 -0
  287. package/dist/cli/index.d.ts +22 -0
  288. package/dist/cli/index.d.ts.map +1 -0
  289. package/dist/cli/index.js +139 -0
  290. package/dist/cli/index.js.map +1 -0
  291. package/dist/cli/shared/open-graph.d.ts +11 -0
  292. package/dist/cli/shared/open-graph.d.ts.map +1 -0
  293. package/dist/cli/shared/open-graph.js +9 -0
  294. package/dist/cli/shared/open-graph.js.map +1 -0
  295. package/dist/cli/shared/options.d.ts +25 -0
  296. package/dist/cli/shared/options.d.ts.map +1 -0
  297. package/dist/cli/shared/options.js +66 -0
  298. package/dist/cli/shared/options.js.map +1 -0
  299. package/dist/cli/shared/output.d.ts +2 -0
  300. package/dist/cli/shared/output.d.ts.map +1 -0
  301. package/dist/cli/shared/output.js +2 -0
  302. package/dist/cli/shared/output.js.map +1 -0
  303. package/dist/cli/types.d.ts +32 -0
  304. package/dist/cli/types.d.ts.map +1 -0
  305. package/dist/cli/types.js +2 -0
  306. package/dist/cli/types.js.map +1 -0
  307. package/dist/cli.d.ts +3 -0
  308. package/dist/cli.d.ts.map +1 -0
  309. package/dist/cli.js +38 -0
  310. package/dist/cli.js.map +1 -0
  311. package/dist/db/better-sqlite3.d.ts +4 -0
  312. package/dist/db/better-sqlite3.d.ts.map +1 -0
  313. package/dist/db/better-sqlite3.js +19 -0
  314. package/dist/db/better-sqlite3.js.map +1 -0
  315. package/dist/db/connection.d.ts +82 -0
  316. package/dist/db/connection.d.ts.map +1 -0
  317. package/dist/db/connection.js +444 -0
  318. package/dist/db/connection.js.map +1 -0
  319. package/dist/db/index.d.ts +6 -0
  320. package/dist/db/index.d.ts.map +1 -0
  321. package/dist/db/index.js +6 -0
  322. package/dist/db/index.js.map +1 -0
  323. package/dist/db/migrations.d.ts +11 -0
  324. package/dist/db/migrations.d.ts.map +1 -0
  325. package/dist/db/migrations.js +416 -0
  326. package/dist/db/migrations.js.map +1 -0
  327. package/dist/db/query-builder.d.ts +88 -0
  328. package/dist/db/query-builder.d.ts.map +1 -0
  329. package/dist/db/query-builder.js +321 -0
  330. package/dist/db/query-builder.js.map +1 -0
  331. package/dist/db/repository/base.d.ts +103 -0
  332. package/dist/db/repository/base.d.ts.map +1 -0
  333. package/dist/db/repository/base.js +172 -0
  334. package/dist/db/repository/base.js.map +1 -0
  335. package/dist/db/repository/build-stmts.d.ts +16 -0
  336. package/dist/db/repository/build-stmts.d.ts.map +1 -0
  337. package/dist/db/repository/build-stmts.js +76 -0
  338. package/dist/db/repository/build-stmts.js.map +1 -0
  339. package/dist/db/repository/cached-stmt.d.ts +9 -0
  340. package/dist/db/repository/cached-stmt.d.ts.map +1 -0
  341. package/dist/db/repository/cached-stmt.js +15 -0
  342. package/dist/db/repository/cached-stmt.js.map +1 -0
  343. package/dist/db/repository/cfg.d.ts +34 -0
  344. package/dist/db/repository/cfg.d.ts.map +1 -0
  345. package/dist/db/repository/cfg.js +46 -0
  346. package/dist/db/repository/cfg.js.map +1 -0
  347. package/dist/db/repository/cochange.d.ts +14 -0
  348. package/dist/db/repository/cochange.d.ts.map +1 -0
  349. package/dist/db/repository/cochange.js +38 -0
  350. package/dist/db/repository/cochange.js.map +1 -0
  351. package/dist/db/repository/complexity.d.ts +7 -0
  352. package/dist/db/repository/complexity.d.ts.map +1 -0
  353. package/dist/db/repository/complexity.js +12 -0
  354. package/dist/db/repository/complexity.js.map +1 -0
  355. package/dist/db/repository/dataflow.d.ts +11 -0
  356. package/dist/db/repository/dataflow.d.ts.map +1 -0
  357. package/dist/db/repository/dataflow.js +30 -0
  358. package/dist/db/repository/dataflow.js.map +1 -0
  359. package/dist/db/repository/edges.d.ts +66 -0
  360. package/dist/db/repository/edges.d.ts.map +1 -0
  361. package/dist/db/repository/edges.js +175 -0
  362. package/dist/db/repository/edges.js.map +1 -0
  363. package/dist/db/repository/embeddings.d.ts +14 -0
  364. package/dist/db/repository/embeddings.d.ts.map +1 -0
  365. package/dist/db/repository/embeddings.js +40 -0
  366. package/dist/db/repository/embeddings.js.map +1 -0
  367. package/dist/db/repository/graph-read.d.ts +18 -0
  368. package/dist/db/repository/graph-read.d.ts.map +1 -0
  369. package/dist/db/repository/graph-read.js +33 -0
  370. package/dist/db/repository/graph-read.js.map +1 -0
  371. package/dist/db/repository/in-memory-repository.d.ts +88 -0
  372. package/dist/db/repository/in-memory-repository.d.ts.map +1 -0
  373. package/dist/db/repository/in-memory-repository.js +541 -0
  374. package/dist/db/repository/in-memory-repository.js.map +1 -0
  375. package/dist/db/repository/index.d.ts +16 -0
  376. package/dist/db/repository/index.d.ts.map +1 -0
  377. package/dist/db/repository/index.js +16 -0
  378. package/dist/db/repository/index.js.map +1 -0
  379. package/dist/db/repository/native-repository.d.ts +70 -0
  380. package/dist/db/repository/native-repository.d.ts.map +1 -0
  381. package/dist/db/repository/native-repository.js +418 -0
  382. package/dist/db/repository/native-repository.js.map +1 -0
  383. package/dist/db/repository/nodes.d.ts +86 -0
  384. package/dist/db/repository/nodes.d.ts.map +1 -0
  385. package/dist/db/repository/nodes.js +203 -0
  386. package/dist/db/repository/nodes.js.map +1 -0
  387. package/dist/db/repository/sqlite-repository.d.ts +59 -0
  388. package/dist/db/repository/sqlite-repository.d.ts.map +1 -0
  389. package/dist/db/repository/sqlite-repository.js +199 -0
  390. package/dist/db/repository/sqlite-repository.js.map +1 -0
  391. package/dist/domain/analysis/brief.d.ts +25 -0
  392. package/dist/domain/analysis/brief.d.ts.map +1 -0
  393. package/dist/domain/analysis/brief.js +136 -0
  394. package/dist/domain/analysis/brief.js.map +1 -0
  395. package/dist/domain/analysis/context.d.ts +241 -0
  396. package/dist/domain/analysis/context.d.ts.map +1 -0
  397. package/dist/domain/analysis/context.js +361 -0
  398. package/dist/domain/analysis/context.js.map +1 -0
  399. package/dist/domain/analysis/dependencies.d.ts +158 -0
  400. package/dist/domain/analysis/dependencies.d.ts.map +1 -0
  401. package/dist/domain/analysis/dependencies.js +522 -0
  402. package/dist/domain/analysis/dependencies.js.map +1 -0
  403. package/dist/domain/analysis/diff-impact.d.ts +90 -0
  404. package/dist/domain/analysis/diff-impact.d.ts.map +1 -0
  405. package/dist/domain/analysis/diff-impact.js +301 -0
  406. package/dist/domain/analysis/diff-impact.js.map +1 -0
  407. package/dist/domain/analysis/exports.d.ts +8 -0
  408. package/dist/domain/analysis/exports.d.ts.map +1 -0
  409. package/dist/domain/analysis/exports.js +178 -0
  410. package/dist/domain/analysis/exports.js.map +1 -0
  411. package/dist/domain/analysis/fn-impact.d.ts +61 -0
  412. package/dist/domain/analysis/fn-impact.d.ts.map +1 -0
  413. package/dist/domain/analysis/fn-impact.js +190 -0
  414. package/dist/domain/analysis/fn-impact.js.map +1 -0
  415. package/dist/domain/analysis/impact.d.ts +11 -0
  416. package/dist/domain/analysis/impact.d.ts.map +1 -0
  417. package/dist/domain/analysis/impact.js +11 -0
  418. package/dist/domain/analysis/impact.js.map +1 -0
  419. package/dist/domain/analysis/implementations.d.ts +59 -0
  420. package/dist/domain/analysis/implementations.d.ts.map +1 -0
  421. package/dist/domain/analysis/implementations.js +65 -0
  422. package/dist/domain/analysis/implementations.js.map +1 -0
  423. package/dist/domain/analysis/module-map.d.ts +86 -0
  424. package/dist/domain/analysis/module-map.d.ts.map +1 -0
  425. package/dist/domain/analysis/module-map.js +468 -0
  426. package/dist/domain/analysis/module-map.js.map +1 -0
  427. package/dist/domain/analysis/query-helpers.d.ts +27 -0
  428. package/dist/domain/analysis/query-helpers.d.ts.map +1 -0
  429. package/dist/domain/analysis/query-helpers.js +41 -0
  430. package/dist/domain/analysis/query-helpers.js.map +1 -0
  431. package/dist/domain/analysis/roles.d.ts +20 -0
  432. package/dist/domain/analysis/roles.d.ts.map +1 -0
  433. package/dist/domain/analysis/roles.js +74 -0
  434. package/dist/domain/analysis/roles.js.map +1 -0
  435. package/dist/domain/analysis/symbol-lookup.d.ts +125 -0
  436. package/dist/domain/analysis/symbol-lookup.d.ts.map +1 -0
  437. package/dist/domain/analysis/symbol-lookup.js +206 -0
  438. package/dist/domain/analysis/symbol-lookup.js.map +1 -0
  439. package/dist/domain/graph/builder/call-resolver.d.ts +89 -0
  440. package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -0
  441. package/dist/domain/graph/builder/call-resolver.js +212 -0
  442. package/dist/domain/graph/builder/call-resolver.js.map +1 -0
  443. package/dist/domain/graph/builder/cha.d.ts +69 -0
  444. package/dist/domain/graph/builder/cha.d.ts.map +1 -0
  445. package/dist/domain/graph/builder/cha.js +158 -0
  446. package/dist/domain/graph/builder/cha.js.map +1 -0
  447. package/dist/domain/graph/builder/context.d.ts +91 -0
  448. package/dist/domain/graph/builder/context.d.ts.map +1 -0
  449. package/dist/domain/graph/builder/context.js +66 -0
  450. package/dist/domain/graph/builder/context.js.map +1 -0
  451. package/dist/domain/graph/builder/helpers.d.ts +97 -0
  452. package/dist/domain/graph/builder/helpers.d.ts.map +1 -0
  453. package/dist/domain/graph/builder/helpers.js +558 -0
  454. package/dist/domain/graph/builder/helpers.js.map +1 -0
  455. package/dist/domain/graph/builder/incremental.d.ts +53 -0
  456. package/dist/domain/graph/builder/incremental.d.ts.map +1 -0
  457. package/dist/domain/graph/builder/incremental.js +647 -0
  458. package/dist/domain/graph/builder/incremental.js.map +1 -0
  459. package/dist/domain/graph/builder/native-db-proxy.d.ts +24 -0
  460. package/dist/domain/graph/builder/native-db-proxy.d.ts.map +1 -0
  461. package/dist/domain/graph/builder/native-db-proxy.js +91 -0
  462. package/dist/domain/graph/builder/native-db-proxy.js.map +1 -0
  463. package/dist/domain/graph/builder/pipeline.d.ts +9 -0
  464. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -0
  465. package/dist/domain/graph/builder/pipeline.js +448 -0
  466. package/dist/domain/graph/builder/pipeline.js.map +1 -0
  467. package/dist/domain/graph/builder/stages/build-edges.d.ts +3 -0
  468. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -0
  469. package/dist/domain/graph/builder/stages/build-edges.js +1425 -0
  470. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -0
  471. package/dist/domain/graph/builder/stages/build-structure.d.ts +3 -0
  472. package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -0
  473. package/dist/domain/graph/builder/stages/build-structure.js +250 -0
  474. package/dist/domain/graph/builder/stages/build-structure.js.map +1 -0
  475. package/dist/domain/graph/builder/stages/collect-files.d.ts +3 -0
  476. package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -0
  477. package/dist/domain/graph/builder/stages/collect-files.js +161 -0
  478. package/dist/domain/graph/builder/stages/collect-files.js.map +1 -0
  479. package/dist/domain/graph/builder/stages/detect-changes.d.ts +27 -0
  480. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -0
  481. package/dist/domain/graph/builder/stages/detect-changes.js +593 -0
  482. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -0
  483. package/dist/domain/graph/builder/stages/finalize.d.ts +3 -0
  484. package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -0
  485. package/dist/domain/graph/builder/stages/finalize.js +274 -0
  486. package/dist/domain/graph/builder/stages/finalize.js.map +1 -0
  487. package/dist/domain/graph/builder/stages/insert-nodes.d.ts +35 -0
  488. package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -0
  489. package/dist/domain/graph/builder/stages/insert-nodes.js +351 -0
  490. package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -0
  491. package/dist/domain/graph/builder/stages/native-db-lifecycle.d.ts +14 -0
  492. package/dist/domain/graph/builder/stages/native-db-lifecycle.d.ts.map +1 -0
  493. package/dist/domain/graph/builder/stages/native-db-lifecycle.js +77 -0
  494. package/dist/domain/graph/builder/stages/native-db-lifecycle.js.map +1 -0
  495. package/dist/domain/graph/builder/stages/native-orchestrator.d.ts +62 -0
  496. package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -0
  497. package/dist/domain/graph/builder/stages/native-orchestrator.js +1763 -0
  498. package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -0
  499. package/dist/domain/graph/builder/stages/parse-files.d.ts +3 -0
  500. package/dist/domain/graph/builder/stages/parse-files.d.ts.map +1 -0
  501. package/dist/domain/graph/builder/stages/parse-files.js +22 -0
  502. package/dist/domain/graph/builder/stages/parse-files.js.map +1 -0
  503. package/dist/domain/graph/builder/stages/resolve-imports.d.ts +7 -0
  504. package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -0
  505. package/dist/domain/graph/builder/stages/resolve-imports.js +231 -0
  506. package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -0
  507. package/dist/domain/graph/builder/stages/run-analyses.d.ts +3 -0
  508. package/dist/domain/graph/builder/stages/run-analyses.d.ts.map +1 -0
  509. package/dist/domain/graph/builder/stages/run-analyses.js +23 -0
  510. package/dist/domain/graph/builder/stages/run-analyses.js.map +1 -0
  511. package/dist/domain/graph/builder.d.ts +4 -0
  512. package/dist/domain/graph/builder.d.ts.map +1 -0
  513. package/dist/domain/graph/builder.js +6 -0
  514. package/dist/domain/graph/builder.js.map +1 -0
  515. package/dist/domain/graph/change-journal.d.ts +50 -0
  516. package/dist/domain/graph/change-journal.d.ts.map +1 -0
  517. package/dist/domain/graph/change-journal.js +97 -0
  518. package/dist/domain/graph/change-journal.js.map +1 -0
  519. package/dist/domain/graph/cycles.d.ts +19 -0
  520. package/dist/domain/graph/cycles.d.ts.map +1 -0
  521. package/dist/domain/graph/cycles.js +142 -0
  522. package/dist/domain/graph/cycles.js.map +1 -0
  523. package/dist/domain/graph/journal.d.ts +30 -0
  524. package/dist/domain/graph/journal.d.ts.map +1 -0
  525. package/dist/domain/graph/journal.js +360 -0
  526. package/dist/domain/graph/journal.js.map +1 -0
  527. package/dist/domain/graph/resolve.d.ts +67 -0
  528. package/dist/domain/graph/resolve.d.ts.map +1 -0
  529. package/dist/domain/graph/resolve.js +521 -0
  530. package/dist/domain/graph/resolve.js.map +1 -0
  531. package/dist/domain/graph/resolver/points-to.d.ts +53 -0
  532. package/dist/domain/graph/resolver/points-to.d.ts.map +1 -0
  533. package/dist/domain/graph/resolver/points-to.js +261 -0
  534. package/dist/domain/graph/resolver/points-to.js.map +1 -0
  535. package/dist/domain/graph/resolver/strategy.d.ts +61 -0
  536. package/dist/domain/graph/resolver/strategy.d.ts.map +1 -0
  537. package/dist/domain/graph/resolver/strategy.js +222 -0
  538. package/dist/domain/graph/resolver/strategy.js.map +1 -0
  539. package/dist/domain/graph/resolver/ts-resolver.d.ts +9 -0
  540. package/dist/domain/graph/resolver/ts-resolver.d.ts.map +1 -0
  541. package/dist/domain/graph/resolver/ts-resolver.js +476 -0
  542. package/dist/domain/graph/resolver/ts-resolver.js.map +1 -0
  543. package/dist/domain/graph/watcher.d.ts +23 -0
  544. package/dist/domain/graph/watcher.d.ts.map +1 -0
  545. package/dist/domain/graph/watcher.js +272 -0
  546. package/dist/domain/graph/watcher.js.map +1 -0
  547. package/dist/domain/parser.d.ts +128 -0
  548. package/dist/domain/parser.d.ts.map +1 -0
  549. package/dist/domain/parser.js +1246 -0
  550. package/dist/domain/parser.js.map +1 -0
  551. package/dist/domain/queries.d.ts +22 -0
  552. package/dist/domain/queries.d.ts.map +1 -0
  553. package/dist/domain/queries.js +26 -0
  554. package/dist/domain/queries.js.map +1 -0
  555. package/dist/domain/search/generator.d.ts +16 -0
  556. package/dist/domain/search/generator.d.ts.map +1 -0
  557. package/dist/domain/search/generator.js +181 -0
  558. package/dist/domain/search/generator.js.map +1 -0
  559. package/dist/domain/search/index.d.ts +15 -0
  560. package/dist/domain/search/index.d.ts.map +1 -0
  561. package/dist/domain/search/index.js +13 -0
  562. package/dist/domain/search/index.js.map +1 -0
  563. package/dist/domain/search/models.d.ts +63 -0
  564. package/dist/domain/search/models.d.ts.map +1 -0
  565. package/dist/domain/search/models.js +303 -0
  566. package/dist/domain/search/models.js.map +1 -0
  567. package/dist/domain/search/search/cli-formatter.d.ts +10 -0
  568. package/dist/domain/search/search/cli-formatter.d.ts.map +1 -0
  569. package/dist/domain/search/search/cli-formatter.js +134 -0
  570. package/dist/domain/search/search/cli-formatter.js.map +1 -0
  571. package/dist/domain/search/search/filters.d.ts +9 -0
  572. package/dist/domain/search/search/filters.d.ts.map +1 -0
  573. package/dist/domain/search/search/filters.js +31 -0
  574. package/dist/domain/search/search/filters.js.map +1 -0
  575. package/dist/domain/search/search/hybrid.d.ts +21 -0
  576. package/dist/domain/search/search/hybrid.d.ts.map +1 -0
  577. package/dist/domain/search/search/hybrid.js +122 -0
  578. package/dist/domain/search/search/hybrid.js.map +1 -0
  579. package/dist/domain/search/search/keyword.d.ts +18 -0
  580. package/dist/domain/search/search/keyword.d.ts.map +1 -0
  581. package/dist/domain/search/search/keyword.js +58 -0
  582. package/dist/domain/search/search/keyword.js.map +1 -0
  583. package/dist/domain/search/search/prepare.d.ts +25 -0
  584. package/dist/domain/search/search/prepare.d.ts.map +1 -0
  585. package/dist/domain/search/search/prepare.js +63 -0
  586. package/dist/domain/search/search/prepare.js.map +1 -0
  587. package/dist/domain/search/search/semantic.d.ts +41 -0
  588. package/dist/domain/search/search/semantic.d.ts.map +1 -0
  589. package/dist/domain/search/search/semantic.js +135 -0
  590. package/dist/domain/search/search/semantic.js.map +1 -0
  591. package/dist/domain/search/stores/fts5.d.ts +10 -0
  592. package/dist/domain/search/stores/fts5.d.ts.map +1 -0
  593. package/dist/domain/search/stores/fts5.js +27 -0
  594. package/dist/domain/search/stores/fts5.js.map +1 -0
  595. package/dist/domain/search/stores/sqlite-blob.d.ts +5 -0
  596. package/dist/domain/search/stores/sqlite-blob.d.ts.map +1 -0
  597. package/dist/domain/search/stores/sqlite-blob.js +16 -0
  598. package/dist/domain/search/stores/sqlite-blob.js.map +1 -0
  599. package/dist/domain/search/strategies/source.d.ts +6 -0
  600. package/dist/domain/search/strategies/source.d.ts.map +1 -0
  601. package/dist/domain/search/strategies/source.js +14 -0
  602. package/dist/domain/search/strategies/source.js.map +1 -0
  603. package/dist/domain/search/strategies/structured.d.ts +10 -0
  604. package/dist/domain/search/strategies/structured.d.ts.map +1 -0
  605. package/dist/domain/search/strategies/structured.js +35 -0
  606. package/dist/domain/search/strategies/structured.js.map +1 -0
  607. package/dist/domain/search/strategies/text-utils.d.ts +9 -0
  608. package/dist/domain/search/strategies/text-utils.d.ts.map +1 -0
  609. package/dist/domain/search/strategies/text-utils.js +45 -0
  610. package/dist/domain/search/strategies/text-utils.js.map +1 -0
  611. package/dist/domain/wasm-worker-entry.d.ts +24 -0
  612. package/dist/domain/wasm-worker-entry.d.ts.map +1 -0
  613. package/dist/domain/wasm-worker-entry.js +749 -0
  614. package/dist/domain/wasm-worker-entry.js.map +1 -0
  615. package/dist/domain/wasm-worker-pool.d.ts +59 -0
  616. package/dist/domain/wasm-worker-pool.d.ts.map +1 -0
  617. package/dist/domain/wasm-worker-pool.js +363 -0
  618. package/dist/domain/wasm-worker-pool.js.map +1 -0
  619. package/dist/domain/wasm-worker-protocol.d.ts +81 -0
  620. package/dist/domain/wasm-worker-protocol.d.ts.map +1 -0
  621. package/dist/domain/wasm-worker-protocol.js +13 -0
  622. package/dist/domain/wasm-worker-protocol.js.map +1 -0
  623. package/dist/extractors/bash.d.ts +6 -0
  624. package/dist/extractors/bash.d.ts.map +1 -0
  625. package/dist/extractors/bash.js +91 -0
  626. package/dist/extractors/bash.js.map +1 -0
  627. package/dist/extractors/c.d.ts +6 -0
  628. package/dist/extractors/c.d.ts.map +1 -0
  629. package/dist/extractors/c.js +223 -0
  630. package/dist/extractors/c.js.map +1 -0
  631. package/dist/extractors/clojure.d.ts +12 -0
  632. package/dist/extractors/clojure.d.ts.map +1 -0
  633. package/dist/extractors/clojure.js +245 -0
  634. package/dist/extractors/clojure.js.map +1 -0
  635. package/dist/extractors/cpp.d.ts +6 -0
  636. package/dist/extractors/cpp.d.ts.map +1 -0
  637. package/dist/extractors/cpp.js +365 -0
  638. package/dist/extractors/cpp.js.map +1 -0
  639. package/dist/extractors/csharp.d.ts +6 -0
  640. package/dist/extractors/csharp.d.ts.map +1 -0
  641. package/dist/extractors/csharp.js +430 -0
  642. package/dist/extractors/csharp.js.map +1 -0
  643. package/dist/extractors/cuda.d.ts +11 -0
  644. package/dist/extractors/cuda.d.ts.map +1 -0
  645. package/dist/extractors/cuda.js +419 -0
  646. package/dist/extractors/cuda.js.map +1 -0
  647. package/dist/extractors/dart.d.ts +6 -0
  648. package/dist/extractors/dart.d.ts.map +1 -0
  649. package/dist/extractors/dart.js +277 -0
  650. package/dist/extractors/dart.js.map +1 -0
  651. package/dist/extractors/elixir.d.ts +9 -0
  652. package/dist/extractors/elixir.d.ts.map +1 -0
  653. package/dist/extractors/elixir.js +327 -0
  654. package/dist/extractors/elixir.js.map +1 -0
  655. package/dist/extractors/erlang.d.ts +14 -0
  656. package/dist/extractors/erlang.d.ts.map +1 -0
  657. package/dist/extractors/erlang.js +275 -0
  658. package/dist/extractors/erlang.js.map +1 -0
  659. package/dist/extractors/fsharp.d.ts +20 -0
  660. package/dist/extractors/fsharp.d.ts.map +1 -0
  661. package/dist/extractors/fsharp.js +312 -0
  662. package/dist/extractors/fsharp.js.map +1 -0
  663. package/dist/extractors/gleam.d.ts +14 -0
  664. package/dist/extractors/gleam.d.ts.map +1 -0
  665. package/dist/extractors/gleam.js +225 -0
  666. package/dist/extractors/gleam.js.map +1 -0
  667. package/dist/extractors/go.d.ts +6 -0
  668. package/dist/extractors/go.d.ts.map +1 -0
  669. package/dist/extractors/go.js +460 -0
  670. package/dist/extractors/go.js.map +1 -0
  671. package/dist/extractors/groovy.d.ts +10 -0
  672. package/dist/extractors/groovy.d.ts.map +1 -0
  673. package/dist/extractors/groovy.js +403 -0
  674. package/dist/extractors/groovy.js.map +1 -0
  675. package/dist/extractors/haskell.d.ts +8 -0
  676. package/dist/extractors/haskell.d.ts.map +1 -0
  677. package/dist/extractors/haskell.js +261 -0
  678. package/dist/extractors/haskell.js.map +1 -0
  679. package/dist/extractors/hcl.d.ts +6 -0
  680. package/dist/extractors/hcl.d.ts.map +1 -0
  681. package/dist/extractors/hcl.js +114 -0
  682. package/dist/extractors/hcl.js.map +1 -0
  683. package/dist/extractors/helpers.d.ts +144 -0
  684. package/dist/extractors/helpers.d.ts.map +1 -0
  685. package/dist/extractors/helpers.js +360 -0
  686. package/dist/extractors/helpers.js.map +1 -0
  687. package/dist/extractors/index.d.ts +33 -0
  688. package/dist/extractors/index.d.ts.map +1 -0
  689. package/dist/extractors/index.js +33 -0
  690. package/dist/extractors/index.js.map +1 -0
  691. package/dist/extractors/java.d.ts +6 -0
  692. package/dist/extractors/java.d.ts.map +1 -0
  693. package/dist/extractors/java.js +390 -0
  694. package/dist/extractors/java.js.map +1 -0
  695. package/dist/extractors/javascript.d.ts +10 -0
  696. package/dist/extractors/javascript.d.ts.map +1 -0
  697. package/dist/extractors/javascript.js +3618 -0
  698. package/dist/extractors/javascript.js.map +1 -0
  699. package/dist/extractors/julia.d.ts +16 -0
  700. package/dist/extractors/julia.d.ts.map +1 -0
  701. package/dist/extractors/julia.js +411 -0
  702. package/dist/extractors/julia.js.map +1 -0
  703. package/dist/extractors/kotlin.d.ts +6 -0
  704. package/dist/extractors/kotlin.d.ts.map +1 -0
  705. package/dist/extractors/kotlin.js +340 -0
  706. package/dist/extractors/kotlin.js.map +1 -0
  707. package/dist/extractors/lua.d.ts +6 -0
  708. package/dist/extractors/lua.d.ts.map +1 -0
  709. package/dist/extractors/lua.js +162 -0
  710. package/dist/extractors/lua.js.map +1 -0
  711. package/dist/extractors/objc.d.ts +9 -0
  712. package/dist/extractors/objc.d.ts.map +1 -0
  713. package/dist/extractors/objc.js +543 -0
  714. package/dist/extractors/objc.js.map +1 -0
  715. package/dist/extractors/ocaml.d.ts +6 -0
  716. package/dist/extractors/ocaml.d.ts.map +1 -0
  717. package/dist/extractors/ocaml.js +310 -0
  718. package/dist/extractors/ocaml.js.map +1 -0
  719. package/dist/extractors/php.d.ts +6 -0
  720. package/dist/extractors/php.d.ts.map +1 -0
  721. package/dist/extractors/php.js +381 -0
  722. package/dist/extractors/php.js.map +1 -0
  723. package/dist/extractors/python.d.ts +6 -0
  724. package/dist/extractors/python.d.ts.map +1 -0
  725. package/dist/extractors/python.js +428 -0
  726. package/dist/extractors/python.js.map +1 -0
  727. package/dist/extractors/r.d.ts +13 -0
  728. package/dist/extractors/r.d.ts.map +1 -0
  729. package/dist/extractors/r.js +267 -0
  730. package/dist/extractors/r.js.map +1 -0
  731. package/dist/extractors/ruby.d.ts +6 -0
  732. package/dist/extractors/ruby.d.ts.map +1 -0
  733. package/dist/extractors/ruby.js +281 -0
  734. package/dist/extractors/ruby.js.map +1 -0
  735. package/dist/extractors/rust.d.ts +6 -0
  736. package/dist/extractors/rust.d.ts.map +1 -0
  737. package/dist/extractors/rust.js +354 -0
  738. package/dist/extractors/rust.js.map +1 -0
  739. package/dist/extractors/scala.d.ts +6 -0
  740. package/dist/extractors/scala.d.ts.map +1 -0
  741. package/dist/extractors/scala.js +315 -0
  742. package/dist/extractors/scala.js.map +1 -0
  743. package/dist/extractors/solidity.d.ts +9 -0
  744. package/dist/extractors/solidity.d.ts.map +1 -0
  745. package/dist/extractors/solidity.js +351 -0
  746. package/dist/extractors/solidity.js.map +1 -0
  747. package/dist/extractors/swift.d.ts +6 -0
  748. package/dist/extractors/swift.d.ts.map +1 -0
  749. package/dist/extractors/swift.js +326 -0
  750. package/dist/extractors/swift.js.map +1 -0
  751. package/dist/extractors/verilog.d.ts +9 -0
  752. package/dist/extractors/verilog.d.ts.map +1 -0
  753. package/dist/extractors/verilog.js +351 -0
  754. package/dist/extractors/verilog.js.map +1 -0
  755. package/dist/extractors/zig.d.ts +9 -0
  756. package/dist/extractors/zig.d.ts.map +1 -0
  757. package/dist/extractors/zig.js +274 -0
  758. package/dist/extractors/zig.js.map +1 -0
  759. package/dist/features/ast.d.ts +78 -0
  760. package/dist/features/ast.d.ts.map +1 -0
  761. package/dist/features/ast.js +228 -0
  762. package/dist/features/ast.js.map +1 -0
  763. package/dist/features/audit.d.ts +15 -0
  764. package/dist/features/audit.d.ts.map +1 -0
  765. package/dist/features/audit.js +275 -0
  766. package/dist/features/audit.js.map +1 -0
  767. package/dist/features/batch.d.ts +54 -0
  768. package/dist/features/batch.d.ts.map +1 -0
  769. package/dist/features/batch.js +97 -0
  770. package/dist/features/batch.js.map +1 -0
  771. package/dist/features/boundaries.d.ts +51 -0
  772. package/dist/features/boundaries.d.ts.map +1 -0
  773. package/dist/features/boundaries.js +248 -0
  774. package/dist/features/boundaries.js.map +1 -0
  775. package/dist/features/branch-compare.d.ts +71 -0
  776. package/dist/features/branch-compare.d.ts.map +1 -0
  777. package/dist/features/branch-compare.js +444 -0
  778. package/dist/features/branch-compare.js.map +1 -0
  779. package/dist/features/cfg.d.ts +79 -0
  780. package/dist/features/cfg.d.ts.map +1 -0
  781. package/dist/features/cfg.js +483 -0
  782. package/dist/features/cfg.js.map +1 -0
  783. package/dist/features/check.d.ts +84 -0
  784. package/dist/features/check.d.ts.map +1 -0
  785. package/dist/features/check.js +290 -0
  786. package/dist/features/check.js.map +1 -0
  787. package/dist/features/cochange.d.ts +68 -0
  788. package/dist/features/cochange.d.ts.map +1 -0
  789. package/dist/features/cochange.js +384 -0
  790. package/dist/features/cochange.js.map +1 -0
  791. package/dist/features/communities.d.ts +26 -0
  792. package/dist/features/communities.d.ts.map +1 -0
  793. package/dist/features/communities.js +149 -0
  794. package/dist/features/communities.js.map +1 -0
  795. package/dist/features/complexity-query.d.ts +37 -0
  796. package/dist/features/complexity-query.d.ts.map +1 -0
  797. package/dist/features/complexity-query.js +268 -0
  798. package/dist/features/complexity-query.js.map +1 -0
  799. package/dist/features/complexity.d.ts +52 -0
  800. package/dist/features/complexity.d.ts.map +1 -0
  801. package/dist/features/complexity.js +490 -0
  802. package/dist/features/complexity.js.map +1 -0
  803. package/dist/features/dataflow.d.ts +129 -0
  804. package/dist/features/dataflow.d.ts.map +1 -0
  805. package/dist/features/dataflow.js +1079 -0
  806. package/dist/features/dataflow.js.map +1 -0
  807. package/dist/features/export.d.ts +35 -0
  808. package/dist/features/export.d.ts.map +1 -0
  809. package/dist/features/export.js +340 -0
  810. package/dist/features/export.js.map +1 -0
  811. package/dist/features/flow.d.ts +21 -0
  812. package/dist/features/flow.d.ts.map +1 -0
  813. package/dist/features/flow.js +195 -0
  814. package/dist/features/flow.js.map +1 -0
  815. package/dist/features/graph-enrichment.d.ts +44 -0
  816. package/dist/features/graph-enrichment.d.ts.map +1 -0
  817. package/dist/features/graph-enrichment.js +312 -0
  818. package/dist/features/graph-enrichment.js.map +1 -0
  819. package/dist/features/manifesto.d.ts +23 -0
  820. package/dist/features/manifesto.d.ts.map +1 -0
  821. package/dist/features/manifesto.js +382 -0
  822. package/dist/features/manifesto.js.map +1 -0
  823. package/dist/features/owners.d.ts +60 -0
  824. package/dist/features/owners.d.ts.map +1 -0
  825. package/dist/features/owners.js +248 -0
  826. package/dist/features/owners.js.map +1 -0
  827. package/dist/features/sequence.d.ts +42 -0
  828. package/dist/features/sequence.d.ts.map +1 -0
  829. package/dist/features/sequence.js +271 -0
  830. package/dist/features/sequence.js.map +1 -0
  831. package/dist/features/shared/find-nodes.d.ts +7 -0
  832. package/dist/features/shared/find-nodes.d.ts.map +1 -0
  833. package/dist/features/shared/find-nodes.js +18 -0
  834. package/dist/features/shared/find-nodes.js.map +1 -0
  835. package/dist/features/snapshot.d.ts +25 -0
  836. package/dist/features/snapshot.d.ts.map +1 -0
  837. package/dist/features/snapshot.js +188 -0
  838. package/dist/features/snapshot.js.map +1 -0
  839. package/dist/features/structure-query.d.ts +76 -0
  840. package/dist/features/structure-query.d.ts.map +1 -0
  841. package/dist/features/structure-query.js +274 -0
  842. package/dist/features/structure-query.js.map +1 -0
  843. package/dist/features/structure.d.ts +39 -0
  844. package/dist/features/structure.d.ts.map +1 -0
  845. package/dist/features/structure.js +796 -0
  846. package/dist/features/structure.js.map +1 -0
  847. package/dist/features/triage.d.ts +47 -0
  848. package/dist/features/triage.d.ts.map +1 -0
  849. package/dist/features/triage.js +123 -0
  850. package/dist/features/triage.js.map +1 -0
  851. package/dist/graph/algorithms/bfs.d.ts +14 -0
  852. package/dist/graph/algorithms/bfs.d.ts.map +1 -0
  853. package/dist/graph/algorithms/bfs.js +72 -0
  854. package/dist/graph/algorithms/bfs.js.map +1 -0
  855. package/dist/graph/algorithms/centrality.d.ts +12 -0
  856. package/dist/graph/algorithms/centrality.d.ts.map +1 -0
  857. package/dist/graph/algorithms/centrality.js +42 -0
  858. package/dist/graph/algorithms/centrality.js.map +1 -0
  859. package/dist/graph/algorithms/index.d.ts +7 -0
  860. package/dist/graph/algorithms/index.d.ts.map +1 -0
  861. package/dist/graph/algorithms/index.js +7 -0
  862. package/dist/graph/algorithms/index.js.map +1 -0
  863. package/dist/graph/algorithms/leiden/adapter.d.ts +37 -0
  864. package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -0
  865. package/dist/graph/algorithms/leiden/adapter.js +173 -0
  866. package/dist/graph/algorithms/leiden/adapter.js.map +1 -0
  867. package/dist/graph/algorithms/leiden/cpm.d.ts +28 -0
  868. package/dist/graph/algorithms/leiden/cpm.d.ts.map +1 -0
  869. package/dist/graph/algorithms/leiden/cpm.js +48 -0
  870. package/dist/graph/algorithms/leiden/cpm.js.map +1 -0
  871. package/dist/graph/algorithms/leiden/index.d.ts +37 -0
  872. package/dist/graph/algorithms/leiden/index.d.ts.map +1 -0
  873. package/dist/graph/algorithms/leiden/index.js +157 -0
  874. package/dist/graph/algorithms/leiden/index.js.map +1 -0
  875. package/dist/graph/algorithms/leiden/modularity.d.ts +33 -0
  876. package/dist/graph/algorithms/leiden/modularity.d.ts.map +1 -0
  877. package/dist/graph/algorithms/leiden/modularity.js +80 -0
  878. package/dist/graph/algorithms/leiden/modularity.js.map +1 -0
  879. package/dist/graph/algorithms/leiden/optimiser.d.ts +62 -0
  880. package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -0
  881. package/dist/graph/algorithms/leiden/optimiser.js +530 -0
  882. package/dist/graph/algorithms/leiden/optimiser.js.map +1 -0
  883. package/dist/graph/algorithms/leiden/partition.d.ts +44 -0
  884. package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -0
  885. package/dist/graph/algorithms/leiden/partition.js +438 -0
  886. package/dist/graph/algorithms/leiden/partition.js.map +1 -0
  887. package/dist/graph/algorithms/leiden/rng.d.ts +9 -0
  888. package/dist/graph/algorithms/leiden/rng.d.ts.map +1 -0
  889. package/dist/graph/algorithms/leiden/rng.js +17 -0
  890. package/dist/graph/algorithms/leiden/rng.js.map +1 -0
  891. package/dist/graph/algorithms/louvain.d.ts +20 -0
  892. package/dist/graph/algorithms/louvain.d.ts.map +1 -0
  893. package/dist/graph/algorithms/louvain.js +52 -0
  894. package/dist/graph/algorithms/louvain.js.map +1 -0
  895. package/dist/graph/algorithms/shortest-path.d.ts +10 -0
  896. package/dist/graph/algorithms/shortest-path.d.ts.map +1 -0
  897. package/dist/graph/algorithms/shortest-path.js +55 -0
  898. package/dist/graph/algorithms/shortest-path.js.map +1 -0
  899. package/dist/graph/algorithms/tarjan.d.ts +9 -0
  900. package/dist/graph/algorithms/tarjan.d.ts.map +1 -0
  901. package/dist/graph/algorithms/tarjan.js +52 -0
  902. package/dist/graph/algorithms/tarjan.js.map +1 -0
  903. package/dist/graph/builders/dependency.d.ts +18 -0
  904. package/dist/graph/builders/dependency.d.ts.map +1 -0
  905. package/dist/graph/builders/dependency.js +101 -0
  906. package/dist/graph/builders/dependency.js.map +1 -0
  907. package/dist/graph/builders/index.d.ts +4 -0
  908. package/dist/graph/builders/index.d.ts.map +1 -0
  909. package/dist/graph/builders/index.js +4 -0
  910. package/dist/graph/builders/index.js.map +1 -0
  911. package/dist/graph/builders/structure.d.ts +10 -0
  912. package/dist/graph/builders/structure.d.ts.map +1 -0
  913. package/dist/graph/builders/structure.js +33 -0
  914. package/dist/graph/builders/structure.js.map +1 -0
  915. package/dist/graph/builders/temporal.d.ts +13 -0
  916. package/dist/graph/builders/temporal.d.ts.map +1 -0
  917. package/dist/graph/builders/temporal.js +29 -0
  918. package/dist/graph/builders/temporal.js.map +1 -0
  919. package/dist/graph/classifiers/index.d.ts +3 -0
  920. package/dist/graph/classifiers/index.d.ts.map +1 -0
  921. package/dist/graph/classifiers/index.js +3 -0
  922. package/dist/graph/classifiers/index.js.map +1 -0
  923. package/dist/graph/classifiers/risk.d.ts +39 -0
  924. package/dist/graph/classifiers/risk.d.ts.map +1 -0
  925. package/dist/graph/classifiers/risk.js +78 -0
  926. package/dist/graph/classifiers/risk.js.map +1 -0
  927. package/dist/graph/classifiers/roles.d.ts +48 -0
  928. package/dist/graph/classifiers/roles.d.ts.map +1 -0
  929. package/dist/graph/classifiers/roles.js +180 -0
  930. package/dist/graph/classifiers/roles.js.map +1 -0
  931. package/dist/graph/index.d.ts +5 -0
  932. package/dist/graph/index.d.ts.map +1 -0
  933. package/dist/graph/index.js +6 -0
  934. package/dist/graph/index.js.map +1 -0
  935. package/dist/graph/model.d.ts +57 -0
  936. package/dist/graph/model.d.ts.map +1 -0
  937. package/dist/graph/model.js +205 -0
  938. package/dist/graph/model.js.map +1 -0
  939. package/dist/index.cjs +16 -0
  940. package/dist/index.d.ts +37 -0
  941. package/dist/index.d.ts.map +1 -0
  942. package/dist/index.js +36 -0
  943. package/dist/index.js.map +1 -0
  944. package/dist/infrastructure/config.d.ts +281 -0
  945. package/dist/infrastructure/config.d.ts.map +1 -0
  946. package/dist/infrastructure/config.js +857 -0
  947. package/dist/infrastructure/config.js.map +1 -0
  948. package/dist/infrastructure/logger.d.ts +7 -0
  949. package/dist/infrastructure/logger.d.ts.map +1 -0
  950. package/dist/infrastructure/logger.js +21 -0
  951. package/dist/infrastructure/logger.js.map +1 -0
  952. package/dist/infrastructure/native.d.ts +38 -0
  953. package/dist/infrastructure/native.d.ts.map +1 -0
  954. package/dist/infrastructure/native.js +182 -0
  955. package/dist/infrastructure/native.js.map +1 -0
  956. package/dist/infrastructure/registry.d.ts +81 -0
  957. package/dist/infrastructure/registry.d.ts.map +1 -0
  958. package/dist/infrastructure/registry.js +229 -0
  959. package/dist/infrastructure/registry.js.map +1 -0
  960. package/dist/infrastructure/result-formatter.d.ts +2 -0
  961. package/dist/infrastructure/result-formatter.d.ts.map +1 -0
  962. package/dist/infrastructure/result-formatter.js +3 -0
  963. package/dist/infrastructure/result-formatter.js.map +1 -0
  964. package/dist/infrastructure/suppress.d.ts +25 -0
  965. package/dist/infrastructure/suppress.d.ts.map +1 -0
  966. package/dist/infrastructure/suppress.js +43 -0
  967. package/dist/infrastructure/suppress.js.map +1 -0
  968. package/dist/infrastructure/test-filter.d.ts +5 -0
  969. package/dist/infrastructure/test-filter.d.ts.map +1 -0
  970. package/dist/infrastructure/test-filter.js +7 -0
  971. package/dist/infrastructure/test-filter.js.map +1 -0
  972. package/dist/infrastructure/update-check.d.ts +26 -0
  973. package/dist/infrastructure/update-check.d.ts.map +1 -0
  974. package/dist/infrastructure/update-check.js +164 -0
  975. package/dist/infrastructure/update-check.js.map +1 -0
  976. package/dist/mcp/index.d.ts +3 -0
  977. package/dist/mcp/index.d.ts.map +1 -0
  978. package/dist/mcp/index.js +3 -0
  979. package/dist/mcp/index.js.map +1 -0
  980. package/dist/mcp/middleware.d.ts +26 -0
  981. package/dist/mcp/middleware.d.ts.map +1 -0
  982. package/dist/mcp/middleware.js +32 -0
  983. package/dist/mcp/middleware.js.map +1 -0
  984. package/dist/mcp/server.d.ts +14 -0
  985. package/dist/mcp/server.d.ts.map +1 -0
  986. package/dist/mcp/server.js +193 -0
  987. package/dist/mcp/server.js.map +1 -0
  988. package/dist/mcp/tool-registry.d.ts +21 -0
  989. package/dist/mcp/tool-registry.d.ts.map +1 -0
  990. package/dist/mcp/tool-registry.js +839 -0
  991. package/dist/mcp/tool-registry.js.map +1 -0
  992. package/dist/mcp/tools/ast-query.d.ts +14 -0
  993. package/dist/mcp/tools/ast-query.d.ts.map +1 -0
  994. package/dist/mcp/tools/ast-query.js +13 -0
  995. package/dist/mcp/tools/ast-query.js.map +1 -0
  996. package/dist/mcp/tools/audit.d.ts +15 -0
  997. package/dist/mcp/tools/audit.d.ts.map +1 -0
  998. package/dist/mcp/tools/audit.js +20 -0
  999. package/dist/mcp/tools/audit.js.map +1 -0
  1000. package/dist/mcp/tools/batch-query.d.ts +13 -0
  1001. package/dist/mcp/tools/batch-query.d.ts.map +1 -0
  1002. package/dist/mcp/tools/batch-query.js +11 -0
  1003. package/dist/mcp/tools/batch-query.js.map +1 -0
  1004. package/dist/mcp/tools/branch-compare.d.ts +12 -0
  1005. package/dist/mcp/tools/branch-compare.d.ts.map +1 -0
  1006. package/dist/mcp/tools/branch-compare.js +10 -0
  1007. package/dist/mcp/tools/branch-compare.js.map +1 -0
  1008. package/dist/mcp/tools/brief.d.ts +9 -0
  1009. package/dist/mcp/tools/brief.d.ts.map +1 -0
  1010. package/dist/mcp/tools/brief.js +8 -0
  1011. package/dist/mcp/tools/brief.js.map +1 -0
  1012. package/dist/mcp/tools/cfg.d.ts +14 -0
  1013. package/dist/mcp/tools/cfg.d.ts.map +1 -0
  1014. package/dist/mcp/tools/cfg.js +20 -0
  1015. package/dist/mcp/tools/cfg.js.map +1 -0
  1016. package/dist/mcp/tools/check.d.ts +20 -0
  1017. package/dist/mcp/tools/check.d.ts.map +1 -0
  1018. package/dist/mcp/tools/check.js +39 -0
  1019. package/dist/mcp/tools/check.js.map +1 -0
  1020. package/dist/mcp/tools/co-changes.d.ts +12 -0
  1021. package/dist/mcp/tools/co-changes.d.ts.map +1 -0
  1022. package/dist/mcp/tools/co-changes.js +19 -0
  1023. package/dist/mcp/tools/co-changes.js.map +1 -0
  1024. package/dist/mcp/tools/code-owners.d.ts +12 -0
  1025. package/dist/mcp/tools/code-owners.d.ts.map +1 -0
  1026. package/dist/mcp/tools/code-owners.js +12 -0
  1027. package/dist/mcp/tools/code-owners.js.map +1 -0
  1028. package/dist/mcp/tools/communities.d.ts +13 -0
  1029. package/dist/mcp/tools/communities.d.ts.map +1 -0
  1030. package/dist/mcp/tools/communities.js +14 -0
  1031. package/dist/mcp/tools/communities.js.map +1 -0
  1032. package/dist/mcp/tools/complexity.d.ts +16 -0
  1033. package/dist/mcp/tools/complexity.d.ts.map +1 -0
  1034. package/dist/mcp/tools/complexity.js +16 -0
  1035. package/dist/mcp/tools/complexity.js.map +1 -0
  1036. package/dist/mcp/tools/context.d.ts +16 -0
  1037. package/dist/mcp/tools/context.d.ts.map +1 -0
  1038. package/dist/mcp/tools/context.js +16 -0
  1039. package/dist/mcp/tools/context.js.map +1 -0
  1040. package/dist/mcp/tools/dataflow.d.ts +15 -0
  1041. package/dist/mcp/tools/dataflow.d.ts.map +1 -0
  1042. package/dist/mcp/tools/dataflow.js +25 -0
  1043. package/dist/mcp/tools/dataflow.js.map +1 -0
  1044. package/dist/mcp/tools/diff-impact.d.ts +14 -0
  1045. package/dist/mcp/tools/diff-impact.d.ts.map +1 -0
  1046. package/dist/mcp/tools/diff-impact.js +23 -0
  1047. package/dist/mcp/tools/diff-impact.js.map +1 -0
  1048. package/dist/mcp/tools/execution-flow.d.ts +15 -0
  1049. package/dist/mcp/tools/execution-flow.d.ts.map +1 -0
  1050. package/dist/mcp/tools/execution-flow.js +25 -0
  1051. package/dist/mcp/tools/execution-flow.js.map +1 -0
  1052. package/dist/mcp/tools/export-graph.d.ts +11 -0
  1053. package/dist/mcp/tools/export-graph.d.ts.map +1 -0
  1054. package/dist/mcp/tools/export-graph.js +57 -0
  1055. package/dist/mcp/tools/export-graph.js.map +1 -0
  1056. package/dist/mcp/tools/file-deps.d.ts +11 -0
  1057. package/dist/mcp/tools/file-deps.d.ts.map +1 -0
  1058. package/dist/mcp/tools/file-deps.js +11 -0
  1059. package/dist/mcp/tools/file-deps.js.map +1 -0
  1060. package/dist/mcp/tools/file-exports.d.ts +12 -0
  1061. package/dist/mcp/tools/file-exports.d.ts.map +1 -0
  1062. package/dist/mcp/tools/file-exports.js +12 -0
  1063. package/dist/mcp/tools/file-exports.js.map +1 -0
  1064. package/dist/mcp/tools/find-cycles.d.ts +7 -0
  1065. package/dist/mcp/tools/find-cycles.d.ts.map +1 -0
  1066. package/dist/mcp/tools/find-cycles.js +15 -0
  1067. package/dist/mcp/tools/find-cycles.js.map +1 -0
  1068. package/dist/mcp/tools/fn-impact.d.ts +14 -0
  1069. package/dist/mcp/tools/fn-impact.d.ts.map +1 -0
  1070. package/dist/mcp/tools/fn-impact.js +14 -0
  1071. package/dist/mcp/tools/fn-impact.js.map +1 -0
  1072. package/dist/mcp/tools/impact-analysis.d.ts +9 -0
  1073. package/dist/mcp/tools/impact-analysis.d.ts.map +1 -0
  1074. package/dist/mcp/tools/impact-analysis.js +8 -0
  1075. package/dist/mcp/tools/impact-analysis.js.map +1 -0
  1076. package/dist/mcp/tools/implementations.d.ts +13 -0
  1077. package/dist/mcp/tools/implementations.d.ts.map +1 -0
  1078. package/dist/mcp/tools/implementations.js +13 -0
  1079. package/dist/mcp/tools/implementations.js.map +1 -0
  1080. package/dist/mcp/tools/index.d.ts +7 -0
  1081. package/dist/mcp/tools/index.d.ts.map +1 -0
  1082. package/dist/mcp/tools/index.js +76 -0
  1083. package/dist/mcp/tools/index.js.map +1 -0
  1084. package/dist/mcp/tools/interfaces.d.ts +13 -0
  1085. package/dist/mcp/tools/interfaces.d.ts.map +1 -0
  1086. package/dist/mcp/tools/interfaces.js +13 -0
  1087. package/dist/mcp/tools/interfaces.js.map +1 -0
  1088. package/dist/mcp/tools/list-functions.d.ts +12 -0
  1089. package/dist/mcp/tools/list-functions.d.ts.map +1 -0
  1090. package/dist/mcp/tools/list-functions.js +13 -0
  1091. package/dist/mcp/tools/list-functions.js.map +1 -0
  1092. package/dist/mcp/tools/list-repos.d.ts +8 -0
  1093. package/dist/mcp/tools/list-repos.d.ts.map +1 -0
  1094. package/dist/mcp/tools/list-repos.js +11 -0
  1095. package/dist/mcp/tools/list-repos.js.map +1 -0
  1096. package/dist/mcp/tools/module-map.d.ts +9 -0
  1097. package/dist/mcp/tools/module-map.d.ts.map +1 -0
  1098. package/dist/mcp/tools/module-map.js +6 -0
  1099. package/dist/mcp/tools/module-map.js.map +1 -0
  1100. package/dist/mcp/tools/node-roles.d.ts +12 -0
  1101. package/dist/mcp/tools/node-roles.d.ts.map +1 -0
  1102. package/dist/mcp/tools/node-roles.js +13 -0
  1103. package/dist/mcp/tools/node-roles.js.map +1 -0
  1104. package/dist/mcp/tools/path.d.ts +15 -0
  1105. package/dist/mcp/tools/path.d.ts.map +1 -0
  1106. package/dist/mcp/tools/path.js +21 -0
  1107. package/dist/mcp/tools/path.js.map +1 -0
  1108. package/dist/mcp/tools/query.d.ts +20 -0
  1109. package/dist/mcp/tools/query.d.ts.map +1 -0
  1110. package/dist/mcp/tools/query.js +29 -0
  1111. package/dist/mcp/tools/query.js.map +1 -0
  1112. package/dist/mcp/tools/semantic-search.d.ts +13 -0
  1113. package/dist/mcp/tools/semantic-search.d.ts.map +1 -0
  1114. package/dist/mcp/tools/semantic-search.js +62 -0
  1115. package/dist/mcp/tools/semantic-search.js.map +1 -0
  1116. package/dist/mcp/tools/sequence.d.ts +16 -0
  1117. package/dist/mcp/tools/sequence.d.ts.map +1 -0
  1118. package/dist/mcp/tools/sequence.js +16 -0
  1119. package/dist/mcp/tools/sequence.js.map +1 -0
  1120. package/dist/mcp/tools/structure.d.ts +13 -0
  1121. package/dist/mcp/tools/structure.d.ts.map +1 -0
  1122. package/dist/mcp/tools/structure.js +14 -0
  1123. package/dist/mcp/tools/structure.js.map +1 -0
  1124. package/dist/mcp/tools/symbol-children.d.ts +13 -0
  1125. package/dist/mcp/tools/symbol-children.d.ts.map +1 -0
  1126. package/dist/mcp/tools/symbol-children.js +13 -0
  1127. package/dist/mcp/tools/symbol-children.js.map +1 -0
  1128. package/dist/mcp/tools/triage.d.ts +17 -0
  1129. package/dist/mcp/tools/triage.d.ts.map +1 -0
  1130. package/dist/mcp/tools/triage.js +34 -0
  1131. package/dist/mcp/tools/triage.js.map +1 -0
  1132. package/dist/mcp/tools/where.d.ts +12 -0
  1133. package/dist/mcp/tools/where.d.ts.map +1 -0
  1134. package/dist/mcp/tools/where.js +12 -0
  1135. package/dist/mcp/tools/where.js.map +1 -0
  1136. package/dist/mcp/types.d.ts +19 -0
  1137. package/dist/mcp/types.d.ts.map +1 -0
  1138. package/dist/mcp/types.js +6 -0
  1139. package/dist/mcp/types.js.map +1 -0
  1140. package/dist/presentation/audit.d.ts +15 -0
  1141. package/dist/presentation/audit.d.ts.map +1 -0
  1142. package/dist/presentation/audit.js +78 -0
  1143. package/dist/presentation/audit.js.map +1 -0
  1144. package/dist/presentation/batch.d.ts +20 -0
  1145. package/dist/presentation/batch.d.ts.map +1 -0
  1146. package/dist/presentation/batch.js +21 -0
  1147. package/dist/presentation/batch.js.map +1 -0
  1148. package/dist/presentation/branch-compare.d.ts +13 -0
  1149. package/dist/presentation/branch-compare.d.ts.map +1 -0
  1150. package/dist/presentation/branch-compare.js +91 -0
  1151. package/dist/presentation/branch-compare.js.map +1 -0
  1152. package/dist/presentation/brief.d.ts +9 -0
  1153. package/dist/presentation/brief.d.ts.map +1 -0
  1154. package/dist/presentation/brief.js +39 -0
  1155. package/dist/presentation/brief.js.map +1 -0
  1156. package/dist/presentation/cfg.d.ts +13 -0
  1157. package/dist/presentation/cfg.d.ts.map +1 -0
  1158. package/dist/presentation/cfg.js +62 -0
  1159. package/dist/presentation/cfg.js.map +1 -0
  1160. package/dist/presentation/check.d.ts +19 -0
  1161. package/dist/presentation/check.d.ts.map +1 -0
  1162. package/dist/presentation/check.js +74 -0
  1163. package/dist/presentation/check.js.map +1 -0
  1164. package/dist/presentation/cochange.d.ts +32 -0
  1165. package/dist/presentation/cochange.d.ts.map +1 -0
  1166. package/dist/presentation/cochange.js +33 -0
  1167. package/dist/presentation/cochange.js.map +1 -0
  1168. package/dist/presentation/colors.d.ts +12 -0
  1169. package/dist/presentation/colors.d.ts.map +1 -0
  1170. package/dist/presentation/colors.js +47 -0
  1171. package/dist/presentation/colors.js.map +1 -0
  1172. package/dist/presentation/communities.d.ts +11 -0
  1173. package/dist/presentation/communities.d.ts.map +1 -0
  1174. package/dist/presentation/communities.js +57 -0
  1175. package/dist/presentation/communities.js.map +1 -0
  1176. package/dist/presentation/complexity.d.ts +17 -0
  1177. package/dist/presentation/complexity.d.ts.map +1 -0
  1178. package/dist/presentation/complexity.js +59 -0
  1179. package/dist/presentation/complexity.js.map +1 -0
  1180. package/dist/presentation/dataflow.d.ts +14 -0
  1181. package/dist/presentation/dataflow.d.ts.map +1 -0
  1182. package/dist/presentation/dataflow.js +100 -0
  1183. package/dist/presentation/dataflow.js.map +1 -0
  1184. package/dist/presentation/diff-impact-mermaid.d.ts +11 -0
  1185. package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -0
  1186. package/dist/presentation/diff-impact-mermaid.js +114 -0
  1187. package/dist/presentation/diff-impact-mermaid.js.map +1 -0
  1188. package/dist/presentation/export.d.ts +130 -0
  1189. package/dist/presentation/export.d.ts.map +1 -0
  1190. package/dist/presentation/export.js +311 -0
  1191. package/dist/presentation/export.js.map +1 -0
  1192. package/dist/presentation/flow.d.ts +16 -0
  1193. package/dist/presentation/flow.d.ts.map +1 -0
  1194. package/dist/presentation/flow.js +85 -0
  1195. package/dist/presentation/flow.js.map +1 -0
  1196. package/dist/presentation/manifesto.d.ts +13 -0
  1197. package/dist/presentation/manifesto.d.ts.map +1 -0
  1198. package/dist/presentation/manifesto.js +51 -0
  1199. package/dist/presentation/manifesto.js.map +1 -0
  1200. package/dist/presentation/owners.d.ts +16 -0
  1201. package/dist/presentation/owners.d.ts.map +1 -0
  1202. package/dist/presentation/owners.js +42 -0
  1203. package/dist/presentation/owners.js.map +1 -0
  1204. package/dist/presentation/queries-cli/exports.d.ts +12 -0
  1205. package/dist/presentation/queries-cli/exports.d.ts.map +1 -0
  1206. package/dist/presentation/queries-cli/exports.js +100 -0
  1207. package/dist/presentation/queries-cli/exports.js.map +1 -0
  1208. package/dist/presentation/queries-cli/impact.d.ts +23 -0
  1209. package/dist/presentation/queries-cli/impact.d.ts.map +1 -0
  1210. package/dist/presentation/queries-cli/impact.js +208 -0
  1211. package/dist/presentation/queries-cli/impact.js.map +1 -0
  1212. package/dist/presentation/queries-cli/index.d.ts +6 -0
  1213. package/dist/presentation/queries-cli/index.d.ts.map +1 -0
  1214. package/dist/presentation/queries-cli/index.js +6 -0
  1215. package/dist/presentation/queries-cli/index.js.map +1 -0
  1216. package/dist/presentation/queries-cli/inspect.d.ts +23 -0
  1217. package/dist/presentation/queries-cli/inspect.d.ts.map +1 -0
  1218. package/dist/presentation/queries-cli/inspect.js +376 -0
  1219. package/dist/presentation/queries-cli/inspect.js.map +1 -0
  1220. package/dist/presentation/queries-cli/overview.d.ts +19 -0
  1221. package/dist/presentation/queries-cli/overview.d.ts.map +1 -0
  1222. package/dist/presentation/queries-cli/overview.js +196 -0
  1223. package/dist/presentation/queries-cli/overview.js.map +1 -0
  1224. package/dist/presentation/queries-cli/path.d.ts +15 -0
  1225. package/dist/presentation/queries-cli/path.d.ts.map +1 -0
  1226. package/dist/presentation/queries-cli/path.js +101 -0
  1227. package/dist/presentation/queries-cli/path.js.map +1 -0
  1228. package/dist/presentation/queries-cli.d.ts +12 -0
  1229. package/dist/presentation/queries-cli.d.ts.map +1 -0
  1230. package/dist/presentation/queries-cli.js +12 -0
  1231. package/dist/presentation/queries-cli.js.map +1 -0
  1232. package/dist/presentation/query.d.ts +2 -0
  1233. package/dist/presentation/query.d.ts.map +1 -0
  1234. package/dist/presentation/query.js +2 -0
  1235. package/dist/presentation/query.js.map +1 -0
  1236. package/dist/presentation/result-formatter.d.ts +23 -0
  1237. package/dist/presentation/result-formatter.d.ts.map +1 -0
  1238. package/dist/presentation/result-formatter.js +122 -0
  1239. package/dist/presentation/result-formatter.js.map +1 -0
  1240. package/dist/presentation/sequence-renderer.d.ts +19 -0
  1241. package/dist/presentation/sequence-renderer.d.ts.map +1 -0
  1242. package/dist/presentation/sequence-renderer.js +23 -0
  1243. package/dist/presentation/sequence-renderer.js.map +1 -0
  1244. package/dist/presentation/sequence.d.ts +15 -0
  1245. package/dist/presentation/sequence.d.ts.map +1 -0
  1246. package/dist/presentation/sequence.js +26 -0
  1247. package/dist/presentation/sequence.js.map +1 -0
  1248. package/dist/presentation/structure.d.ts +46 -0
  1249. package/dist/presentation/structure.d.ts.map +1 -0
  1250. package/dist/presentation/structure.js +50 -0
  1251. package/dist/presentation/structure.js.map +1 -0
  1252. package/dist/presentation/table.d.ts +24 -0
  1253. package/dist/presentation/table.d.ts.map +1 -0
  1254. package/dist/presentation/table.js +33 -0
  1255. package/dist/presentation/table.js.map +1 -0
  1256. package/dist/presentation/triage.d.ts +19 -0
  1257. package/dist/presentation/triage.d.ts.map +1 -0
  1258. package/dist/presentation/triage.js +34 -0
  1259. package/dist/presentation/triage.js.map +1 -0
  1260. package/dist/presentation/viewer.d.ts +102 -0
  1261. package/dist/presentation/viewer.d.ts.map +1 -0
  1262. package/dist/presentation/viewer.js +618 -0
  1263. package/dist/presentation/viewer.js.map +1 -0
  1264. package/dist/shared/constants.d.ts +33 -0
  1265. package/dist/shared/constants.d.ts.map +1 -0
  1266. package/dist/shared/constants.js +54 -0
  1267. package/dist/shared/constants.js.map +1 -0
  1268. package/dist/shared/errors.d.ts +46 -0
  1269. package/dist/shared/errors.d.ts.map +1 -0
  1270. package/dist/shared/errors.js +69 -0
  1271. package/dist/shared/errors.js.map +1 -0
  1272. package/dist/shared/file-utils.d.ts +27 -0
  1273. package/dist/shared/file-utils.d.ts.map +1 -0
  1274. package/dist/shared/file-utils.js +186 -0
  1275. package/dist/shared/file-utils.js.map +1 -0
  1276. package/dist/shared/generators.d.ts +57 -0
  1277. package/dist/shared/generators.d.ts.map +1 -0
  1278. package/dist/shared/generators.js +106 -0
  1279. package/dist/shared/generators.js.map +1 -0
  1280. package/dist/shared/globs.d.ts +40 -0
  1281. package/dist/shared/globs.d.ts.map +1 -0
  1282. package/dist/shared/globs.js +126 -0
  1283. package/dist/shared/globs.js.map +1 -0
  1284. package/dist/shared/hierarchy.d.ts +9 -0
  1285. package/dist/shared/hierarchy.d.ts.map +1 -0
  1286. package/dist/shared/hierarchy.js +68 -0
  1287. package/dist/shared/hierarchy.js.map +1 -0
  1288. package/dist/shared/kinds.d.ts +12 -0
  1289. package/dist/shared/kinds.d.ts.map +1 -0
  1290. package/dist/shared/kinds.js +67 -0
  1291. package/dist/shared/kinds.js.map +1 -0
  1292. package/dist/shared/normalize.d.ts +49 -0
  1293. package/dist/shared/normalize.d.ts.map +1 -0
  1294. package/dist/shared/normalize.js +57 -0
  1295. package/dist/shared/normalize.js.map +1 -0
  1296. package/dist/shared/paginate.d.ts +32 -0
  1297. package/dist/shared/paginate.d.ts.map +1 -0
  1298. package/dist/shared/paginate.js +82 -0
  1299. package/dist/shared/paginate.js.map +1 -0
  1300. package/dist/shared/version.d.ts +2 -0
  1301. package/dist/shared/version.d.ts.map +1 -0
  1302. package/dist/shared/version.js +5 -0
  1303. package/dist/shared/version.js.map +1 -0
  1304. package/dist/types.d.ts +2468 -0
  1305. package/dist/types.d.ts.map +1 -0
  1306. package/dist/types.js +10 -0
  1307. package/dist/types.js.map +1 -0
  1308. package/grammars/tree-sitter-bash.wasm +0 -0
  1309. package/grammars/tree-sitter-c.wasm +0 -0
  1310. package/grammars/tree-sitter-c_sharp.wasm +0 -0
  1311. package/grammars/tree-sitter-clojure.wasm +0 -0
  1312. package/grammars/tree-sitter-cpp.wasm +0 -0
  1313. package/grammars/tree-sitter-cuda.wasm +0 -0
  1314. package/grammars/tree-sitter-dart.wasm +0 -0
  1315. package/grammars/tree-sitter-elixir.wasm +0 -0
  1316. package/grammars/tree-sitter-erlang.wasm +0 -0
  1317. package/grammars/tree-sitter-fsharp.wasm +0 -0
  1318. package/grammars/tree-sitter-fsharp_signature.wasm +0 -0
  1319. package/grammars/tree-sitter-gleam.wasm +0 -0
  1320. package/grammars/tree-sitter-go.wasm +0 -0
  1321. package/grammars/tree-sitter-groovy.wasm +0 -0
  1322. package/grammars/tree-sitter-haskell.wasm +0 -0
  1323. package/grammars/tree-sitter-hcl.wasm +0 -0
  1324. package/grammars/tree-sitter-java.wasm +0 -0
  1325. package/grammars/tree-sitter-javascript.wasm +0 -0
  1326. package/grammars/tree-sitter-julia.wasm +0 -0
  1327. package/grammars/tree-sitter-kotlin.wasm +0 -0
  1328. package/grammars/tree-sitter-lua.wasm +0 -0
  1329. package/grammars/tree-sitter-objc.wasm +0 -0
  1330. package/grammars/tree-sitter-ocaml.wasm +0 -0
  1331. package/grammars/tree-sitter-ocaml_interface.wasm +0 -0
  1332. package/grammars/tree-sitter-php.wasm +0 -0
  1333. package/grammars/tree-sitter-python.wasm +0 -0
  1334. package/grammars/tree-sitter-r.wasm +0 -0
  1335. package/grammars/tree-sitter-ruby.wasm +0 -0
  1336. package/grammars/tree-sitter-rust.wasm +0 -0
  1337. package/grammars/tree-sitter-scala.wasm +0 -0
  1338. package/grammars/tree-sitter-solidity.wasm +0 -0
  1339. package/grammars/tree-sitter-swift.wasm +0 -0
  1340. package/grammars/tree-sitter-tsx.wasm +0 -0
  1341. package/grammars/tree-sitter-typescript.wasm +0 -0
  1342. package/grammars/tree-sitter-verilog.wasm +0 -0
  1343. package/grammars/tree-sitter-zig.wasm +0 -0
  1344. package/package.json +188 -0
  1345. package/src/ast-analysis/engine.ts +926 -0
  1346. package/src/ast-analysis/metrics.ts +150 -0
  1347. package/src/ast-analysis/rules/b2.ts +263 -0
  1348. package/src/ast-analysis/rules/b3.ts +127 -0
  1349. package/src/ast-analysis/rules/b4.ts +378 -0
  1350. package/src/ast-analysis/rules/b5.ts +65 -0
  1351. package/src/ast-analysis/rules/c.ts +157 -0
  1352. package/src/ast-analysis/rules/csharp.ts +210 -0
  1353. package/src/ast-analysis/rules/go.ts +187 -0
  1354. package/src/ast-analysis/rules/index.ts +380 -0
  1355. package/src/ast-analysis/rules/java.ts +181 -0
  1356. package/src/ast-analysis/rules/javascript.ts +249 -0
  1357. package/src/ast-analysis/rules/php.ts +226 -0
  1358. package/src/ast-analysis/rules/python.ts +202 -0
  1359. package/src/ast-analysis/rules/ruby.ts +209 -0
  1360. package/src/ast-analysis/rules/rust.ts +179 -0
  1361. package/src/ast-analysis/shared.ts +223 -0
  1362. package/src/ast-analysis/visitor-utils.ts +278 -0
  1363. package/src/ast-analysis/visitor.ts +266 -0
  1364. package/src/ast-analysis/visitors/ast-store-visitor.ts +334 -0
  1365. package/src/ast-analysis/visitors/cfg-conditionals.ts +227 -0
  1366. package/src/ast-analysis/visitors/cfg-loops.ts +136 -0
  1367. package/src/ast-analysis/visitors/cfg-shared.ts +196 -0
  1368. package/src/ast-analysis/visitors/cfg-try-catch.ts +142 -0
  1369. package/src/ast-analysis/visitors/cfg-visitor.ts +367 -0
  1370. package/src/ast-analysis/visitors/complexity-visitor.ts +328 -0
  1371. package/src/ast-analysis/visitors/dataflow-visitor.ts +571 -0
  1372. package/src/cli/commands/ast.ts +24 -0
  1373. package/src/cli/commands/audit.ts +48 -0
  1374. package/src/cli/commands/batch.ts +66 -0
  1375. package/src/cli/commands/branch-compare.ts +27 -0
  1376. package/src/cli/commands/brief.ts +13 -0
  1377. package/src/cli/commands/build.ts +35 -0
  1378. package/src/cli/commands/cfg.ts +28 -0
  1379. package/src/cli/commands/check.ts +72 -0
  1380. package/src/cli/commands/children.ts +34 -0
  1381. package/src/cli/commands/co-change.ts +72 -0
  1382. package/src/cli/commands/communities.ts +21 -0
  1383. package/src/cli/commands/complexity.ts +48 -0
  1384. package/src/cli/commands/config.ts +353 -0
  1385. package/src/cli/commands/context.ts +36 -0
  1386. package/src/cli/commands/cycles.ts +33 -0
  1387. package/src/cli/commands/dataflow.ts +30 -0
  1388. package/src/cli/commands/deps.ts +18 -0
  1389. package/src/cli/commands/diff-impact.ts +30 -0
  1390. package/src/cli/commands/embed.ts +82 -0
  1391. package/src/cli/commands/export.ts +79 -0
  1392. package/src/cli/commands/exports.ts +15 -0
  1393. package/src/cli/commands/flow.ts +34 -0
  1394. package/src/cli/commands/fn-impact.ts +34 -0
  1395. package/src/cli/commands/impact.ts +13 -0
  1396. package/src/cli/commands/implementations.ts +30 -0
  1397. package/src/cli/commands/info.ts +79 -0
  1398. package/src/cli/commands/interfaces.ts +30 -0
  1399. package/src/cli/commands/map.ts +20 -0
  1400. package/src/cli/commands/mcp.ts +19 -0
  1401. package/src/cli/commands/models.ts +29 -0
  1402. package/src/cli/commands/owners.ts +28 -0
  1403. package/src/cli/commands/path.ts +42 -0
  1404. package/src/cli/commands/plot.ts +110 -0
  1405. package/src/cli/commands/query.ts +51 -0
  1406. package/src/cli/commands/registry.ts +106 -0
  1407. package/src/cli/commands/roles.ts +38 -0
  1408. package/src/cli/commands/search.ts +45 -0
  1409. package/src/cli/commands/sequence.ts +30 -0
  1410. package/src/cli/commands/snapshot.ts +67 -0
  1411. package/src/cli/commands/stats.ts +16 -0
  1412. package/src/cli/commands/structure.ts +55 -0
  1413. package/src/cli/commands/triage.ts +93 -0
  1414. package/src/cli/commands/watch.ts +29 -0
  1415. package/src/cli/commands/where.ts +21 -0
  1416. package/src/cli/index.ts +159 -0
  1417. package/src/cli/shared/open-graph.ts +13 -0
  1418. package/src/cli/shared/options.ts +69 -0
  1419. package/src/cli/shared/output.ts +1 -0
  1420. package/src/cli/types.ts +35 -0
  1421. package/src/cli.ts +37 -0
  1422. package/src/db/better-sqlite3.ts +21 -0
  1423. package/src/db/connection.ts +478 -0
  1424. package/src/db/index.ts +84 -0
  1425. package/src/db/migrations.ts +440 -0
  1426. package/src/db/query-builder.ts +371 -0
  1427. package/src/db/repository/base.ts +269 -0
  1428. package/src/db/repository/build-stmts.ts +126 -0
  1429. package/src/db/repository/cached-stmt.ts +20 -0
  1430. package/src/db/repository/cfg.ts +81 -0
  1431. package/src/db/repository/cochange.ts +48 -0
  1432. package/src/db/repository/complexity.ts +21 -0
  1433. package/src/db/repository/dataflow.ts +35 -0
  1434. package/src/db/repository/edges.ts +281 -0
  1435. package/src/db/repository/embeddings.ts +47 -0
  1436. package/src/db/repository/graph-read.ts +62 -0
  1437. package/src/db/repository/in-memory-repository.ts +657 -0
  1438. package/src/db/repository/index.ts +53 -0
  1439. package/src/db/repository/native-repository.ts +546 -0
  1440. package/src/db/repository/nodes.ts +322 -0
  1441. package/src/db/repository/sqlite-repository.ts +303 -0
  1442. package/src/domain/analysis/brief.ts +165 -0
  1443. package/src/domain/analysis/context.ts +537 -0
  1444. package/src/domain/analysis/dependencies.ts +738 -0
  1445. package/src/domain/analysis/diff-impact.ts +381 -0
  1446. package/src/domain/analysis/exports.ts +262 -0
  1447. package/src/domain/analysis/fn-impact.ts +311 -0
  1448. package/src/domain/analysis/impact.ts +11 -0
  1449. package/src/domain/analysis/implementations.ts +81 -0
  1450. package/src/domain/analysis/module-map.ts +576 -0
  1451. package/src/domain/analysis/query-helpers.ts +52 -0
  1452. package/src/domain/analysis/roles.ts +95 -0
  1453. package/src/domain/analysis/symbol-lookup.ts +284 -0
  1454. package/src/domain/graph/builder/call-resolver.ts +289 -0
  1455. package/src/domain/graph/builder/cha.ts +192 -0
  1456. package/src/domain/graph/builder/context.ts +120 -0
  1457. package/src/domain/graph/builder/helpers.ts +665 -0
  1458. package/src/domain/graph/builder/incremental.ts +987 -0
  1459. package/src/domain/graph/builder/native-db-proxy.ts +104 -0
  1460. package/src/domain/graph/builder/pipeline.ts +517 -0
  1461. package/src/domain/graph/builder/stages/build-edges.ts +1986 -0
  1462. package/src/domain/graph/builder/stages/build-structure.ts +330 -0
  1463. package/src/domain/graph/builder/stages/collect-files.ts +175 -0
  1464. package/src/domain/graph/builder/stages/detect-changes.ts +751 -0
  1465. package/src/domain/graph/builder/stages/finalize.ts +321 -0
  1466. package/src/domain/graph/builder/stages/insert-nodes.ts +489 -0
  1467. package/src/domain/graph/builder/stages/native-db-lifecycle.ts +74 -0
  1468. package/src/domain/graph/builder/stages/native-orchestrator.ts +2241 -0
  1469. package/src/domain/graph/builder/stages/parse-files.ts +26 -0
  1470. package/src/domain/graph/builder/stages/resolve-imports.ts +285 -0
  1471. package/src/domain/graph/builder/stages/run-analyses.ts +26 -0
  1472. package/src/domain/graph/builder.ts +11 -0
  1473. package/src/domain/graph/change-journal.ts +141 -0
  1474. package/src/domain/graph/cycles.ts +155 -0
  1475. package/src/domain/graph/journal.ts +377 -0
  1476. package/src/domain/graph/resolve.ts +579 -0
  1477. package/src/domain/graph/resolver/points-to.ts +377 -0
  1478. package/src/domain/graph/resolver/strategy.ts +265 -0
  1479. package/src/domain/graph/resolver/ts-resolver.ts +536 -0
  1480. package/src/domain/graph/watcher.ts +339 -0
  1481. package/src/domain/parser.ts +1437 -0
  1482. package/src/domain/queries.ts +50 -0
  1483. package/src/domain/search/generator.ts +260 -0
  1484. package/src/domain/search/index.ts +15 -0
  1485. package/src/domain/search/models.ts +356 -0
  1486. package/src/domain/search/search/cli-formatter.ts +179 -0
  1487. package/src/domain/search/search/filters.ts +38 -0
  1488. package/src/domain/search/search/hybrid.ts +197 -0
  1489. package/src/domain/search/search/keyword.ts +101 -0
  1490. package/src/domain/search/search/prepare.ts +95 -0
  1491. package/src/domain/search/search/semantic.ts +226 -0
  1492. package/src/domain/search/stores/fts5.ts +27 -0
  1493. package/src/domain/search/stores/sqlite-blob.ts +15 -0
  1494. package/src/domain/search/strategies/source.ts +19 -0
  1495. package/src/domain/search/strategies/structured.ts +48 -0
  1496. package/src/domain/search/strategies/text-utils.ts +41 -0
  1497. package/src/domain/wasm-worker-entry.ts +921 -0
  1498. package/src/domain/wasm-worker-pool.ts +375 -0
  1499. package/src/domain/wasm-worker-protocol.ts +98 -0
  1500. package/src/extractors/bash.ts +97 -0
  1501. package/src/extractors/c.ts +231 -0
  1502. package/src/extractors/clojure.ts +273 -0
  1503. package/src/extractors/cpp.ts +383 -0
  1504. package/src/extractors/csharp.ts +448 -0
  1505. package/src/extractors/cuda.ts +433 -0
  1506. package/src/extractors/dart.ts +304 -0
  1507. package/src/extractors/elixir.ts +350 -0
  1508. package/src/extractors/erlang.ts +295 -0
  1509. package/src/extractors/fsharp.ts +357 -0
  1510. package/src/extractors/gleam.ts +247 -0
  1511. package/src/extractors/go.ts +512 -0
  1512. package/src/extractors/groovy.ts +436 -0
  1513. package/src/extractors/haskell.ts +276 -0
  1514. package/src/extractors/hcl.ts +136 -0
  1515. package/src/extractors/helpers.ts +449 -0
  1516. package/src/extractors/index.ts +32 -0
  1517. package/src/extractors/java.ts +439 -0
  1518. package/src/extractors/javascript.ts +3844 -0
  1519. package/src/extractors/julia.ts +432 -0
  1520. package/src/extractors/kotlin.ts +358 -0
  1521. package/src/extractors/lua.ts +169 -0
  1522. package/src/extractors/objc.ts +555 -0
  1523. package/src/extractors/ocaml.ts +337 -0
  1524. package/src/extractors/php.ts +399 -0
  1525. package/src/extractors/python.ts +439 -0
  1526. package/src/extractors/r.ts +275 -0
  1527. package/src/extractors/ruby.ts +292 -0
  1528. package/src/extractors/rust.ts +371 -0
  1529. package/src/extractors/scala.ts +335 -0
  1530. package/src/extractors/solidity.ts +375 -0
  1531. package/src/extractors/swift.ts +337 -0
  1532. package/src/extractors/verilog.ts +383 -0
  1533. package/src/extractors/zig.ts +291 -0
  1534. package/src/features/ast.ts +405 -0
  1535. package/src/features/audit.ts +446 -0
  1536. package/src/features/batch.ts +182 -0
  1537. package/src/features/boundaries.ts +345 -0
  1538. package/src/features/branch-compare.ts +618 -0
  1539. package/src/features/cfg.ts +750 -0
  1540. package/src/features/check.ts +454 -0
  1541. package/src/features/cochange.ts +506 -0
  1542. package/src/features/communities.ts +232 -0
  1543. package/src/features/complexity-query.ts +388 -0
  1544. package/src/features/complexity.ts +753 -0
  1545. package/src/features/dataflow.ts +1654 -0
  1546. package/src/features/export.ts +486 -0
  1547. package/src/features/flow.ts +307 -0
  1548. package/src/features/graph-enrichment.ts +493 -0
  1549. package/src/features/manifesto.ts +508 -0
  1550. package/src/features/owners.ts +360 -0
  1551. package/src/features/sequence.ts +410 -0
  1552. package/src/features/shared/find-nodes.ts +28 -0
  1553. package/src/features/snapshot.ts +221 -0
  1554. package/src/features/structure-query.ts +456 -0
  1555. package/src/features/structure.ts +1100 -0
  1556. package/src/features/triage.ts +199 -0
  1557. package/src/graph/algorithms/bfs.ts +92 -0
  1558. package/src/graph/algorithms/centrality.ts +50 -0
  1559. package/src/graph/algorithms/index.ts +6 -0
  1560. package/src/graph/algorithms/leiden/LICENSE +24 -0
  1561. package/src/graph/algorithms/leiden/adapter.ts +252 -0
  1562. package/src/graph/algorithms/leiden/cpm.ts +77 -0
  1563. package/src/graph/algorithms/leiden/index.ts +224 -0
  1564. package/src/graph/algorithms/leiden/modularity.ts +122 -0
  1565. package/src/graph/algorithms/leiden/optimiser.ts +706 -0
  1566. package/src/graph/algorithms/leiden/partition.ts +577 -0
  1567. package/src/graph/algorithms/leiden/rng.ts +20 -0
  1568. package/src/graph/algorithms/louvain.ts +75 -0
  1569. package/src/graph/algorithms/shortest-path.ts +59 -0
  1570. package/src/graph/algorithms/tarjan.ts +55 -0
  1571. package/src/graph/builders/dependency.ts +148 -0
  1572. package/src/graph/builders/index.ts +3 -0
  1573. package/src/graph/builders/structure.ts +58 -0
  1574. package/src/graph/builders/temporal.ts +51 -0
  1575. package/src/graph/classifiers/index.ts +2 -0
  1576. package/src/graph/classifiers/risk.ts +123 -0
  1577. package/src/graph/classifiers/roles.ts +226 -0
  1578. package/src/graph/index.ts +13 -0
  1579. package/src/graph/model.ts +238 -0
  1580. package/src/index.cjs +16 -0
  1581. package/src/index.ts +72 -0
  1582. package/src/infrastructure/config.ts +954 -0
  1583. package/src/infrastructure/logger.ts +24 -0
  1584. package/src/infrastructure/native.ts +199 -0
  1585. package/src/infrastructure/registry.ts +313 -0
  1586. package/src/infrastructure/result-formatter.ts +2 -0
  1587. package/src/infrastructure/suppress.ts +47 -0
  1588. package/src/infrastructure/test-filter.ts +7 -0
  1589. package/src/infrastructure/update-check.ts +196 -0
  1590. package/src/mcp/index.ts +2 -0
  1591. package/src/mcp/middleware.ts +38 -0
  1592. package/src/mcp/server.ts +259 -0
  1593. package/src/mcp/tool-registry.ts +890 -0
  1594. package/src/mcp/tools/ast-query.ts +25 -0
  1595. package/src/mcp/tools/audit.ts +33 -0
  1596. package/src/mcp/tools/batch-query.ts +22 -0
  1597. package/src/mcp/tools/branch-compare.ts +22 -0
  1598. package/src/mcp/tools/brief.ts +15 -0
  1599. package/src/mcp/tools/cfg.ts +32 -0
  1600. package/src/mcp/tools/check.ts +60 -0
  1601. package/src/mcp/tools/co-changes.ts +29 -0
  1602. package/src/mcp/tools/code-owners.ts +22 -0
  1603. package/src/mcp/tools/communities.ts +25 -0
  1604. package/src/mcp/tools/complexity.ts +30 -0
  1605. package/src/mcp/tools/context.ts +30 -0
  1606. package/src/mcp/tools/dataflow.ts +38 -0
  1607. package/src/mcp/tools/diff-impact.ts +35 -0
  1608. package/src/mcp/tools/execution-flow.ts +38 -0
  1609. package/src/mcp/tools/export-graph.ts +67 -0
  1610. package/src/mcp/tools/file-deps.ts +20 -0
  1611. package/src/mcp/tools/file-exports.ts +22 -0
  1612. package/src/mcp/tools/find-cycles.ts +19 -0
  1613. package/src/mcp/tools/fn-impact.ts +26 -0
  1614. package/src/mcp/tools/impact-analysis.ts +15 -0
  1615. package/src/mcp/tools/implementations.ts +24 -0
  1616. package/src/mcp/tools/index.ts +81 -0
  1617. package/src/mcp/tools/interfaces.ts +24 -0
  1618. package/src/mcp/tools/list-functions.ts +23 -0
  1619. package/src/mcp/tools/list-repos.ts +17 -0
  1620. package/src/mcp/tools/module-map.ts +13 -0
  1621. package/src/mcp/tools/node-roles.ts +23 -0
  1622. package/src/mcp/tools/path.ts +34 -0
  1623. package/src/mcp/tools/query.ts +47 -0
  1624. package/src/mcp/tools/semantic-search.ts +76 -0
  1625. package/src/mcp/tools/sequence.ts +30 -0
  1626. package/src/mcp/tools/structure.ts +25 -0
  1627. package/src/mcp/tools/symbol-children.ts +24 -0
  1628. package/src/mcp/tools/triage.ts +50 -0
  1629. package/src/mcp/tools/where.ts +22 -0
  1630. package/src/mcp/types.ts +21 -0
  1631. package/src/presentation/audit.ts +109 -0
  1632. package/src/presentation/batch.ts +50 -0
  1633. package/src/presentation/branch-compare.ts +148 -0
  1634. package/src/presentation/brief.ts +63 -0
  1635. package/src/presentation/cfg.ts +103 -0
  1636. package/src/presentation/check.ts +138 -0
  1637. package/src/presentation/cochange.ts +57 -0
  1638. package/src/presentation/colors.ts +51 -0
  1639. package/src/presentation/communities.ts +114 -0
  1640. package/src/presentation/complexity.ts +127 -0
  1641. package/src/presentation/dataflow.ts +179 -0
  1642. package/src/presentation/diff-impact-mermaid.ts +169 -0
  1643. package/src/presentation/export.ts +509 -0
  1644. package/src/presentation/flow.ts +147 -0
  1645. package/src/presentation/manifesto.ts +92 -0
  1646. package/src/presentation/owners.ts +89 -0
  1647. package/src/presentation/queries-cli/exports.ts +152 -0
  1648. package/src/presentation/queries-cli/impact.ts +340 -0
  1649. package/src/presentation/queries-cli/index.ts +13 -0
  1650. package/src/presentation/queries-cli/inspect.ts +594 -0
  1651. package/src/presentation/queries-cli/overview.ts +375 -0
  1652. package/src/presentation/queries-cli/path.ts +187 -0
  1653. package/src/presentation/queries-cli.ts +30 -0
  1654. package/src/presentation/query.ts +17 -0
  1655. package/src/presentation/result-formatter.ts +161 -0
  1656. package/src/presentation/sequence-renderer.ts +46 -0
  1657. package/src/presentation/sequence.ts +43 -0
  1658. package/src/presentation/structure.ts +109 -0
  1659. package/src/presentation/table.ts +45 -0
  1660. package/src/presentation/triage.ts +84 -0
  1661. package/src/presentation/viewer.ts +715 -0
  1662. package/src/shared/constants.ts +70 -0
  1663. package/src/shared/errors.ts +85 -0
  1664. package/src/shared/file-utils.ts +233 -0
  1665. package/src/shared/generators.ts +176 -0
  1666. package/src/shared/globs.ts +121 -0
  1667. package/src/shared/hierarchy.ts +81 -0
  1668. package/src/shared/kinds.ts +85 -0
  1669. package/src/shared/normalize.ts +106 -0
  1670. package/src/shared/paginate.ts +93 -0
  1671. package/src/shared/version.ts +10 -0
  1672. package/src/types.ts +2871 -0
@@ -0,0 +1,3618 @@
1
+ import { debug } from '../infrastructure/logger.js';
2
+ import { findChild, findParentNode, MAX_WALK_DEPTH, nodeEndLine, nodeStartLine, setTypeMapEntry, } from './helpers.js';
3
+ /** Built-in globals that start with uppercase but are not user-defined types. */
4
+ const BUILTIN_GLOBALS = new Set([
5
+ 'Math',
6
+ 'JSON',
7
+ 'Promise',
8
+ 'Array',
9
+ 'Object',
10
+ 'Date',
11
+ 'Error',
12
+ 'Symbol',
13
+ 'Map',
14
+ 'Set',
15
+ 'RegExp',
16
+ 'Number',
17
+ 'String',
18
+ 'Boolean',
19
+ 'WeakMap',
20
+ 'WeakSet',
21
+ 'WeakRef',
22
+ 'Proxy',
23
+ 'Reflect',
24
+ 'Intl',
25
+ 'ArrayBuffer',
26
+ 'SharedArrayBuffer',
27
+ 'DataView',
28
+ 'Atomics',
29
+ 'BigInt',
30
+ 'Float32Array',
31
+ 'Float64Array',
32
+ 'Int8Array',
33
+ 'Int16Array',
34
+ 'Int32Array',
35
+ 'Uint8Array',
36
+ 'Uint16Array',
37
+ 'Uint32Array',
38
+ 'Uint8ClampedArray',
39
+ 'URL',
40
+ 'URLSearchParams',
41
+ 'TextEncoder',
42
+ 'TextDecoder',
43
+ 'AbortController',
44
+ 'AbortSignal',
45
+ 'Headers',
46
+ 'Request',
47
+ 'Response',
48
+ 'FormData',
49
+ 'Blob',
50
+ 'File',
51
+ 'ReadableStream',
52
+ 'WritableStream',
53
+ 'TransformStream',
54
+ 'console',
55
+ 'Buffer',
56
+ 'EventEmitter',
57
+ 'Stream',
58
+ 'process',
59
+ 'window',
60
+ 'document',
61
+ 'globalThis',
62
+ ]);
63
+ /** Maximum chain depth for inter-procedural return-type propagation (Phase 8.2). */
64
+ const MAX_PROPAGATION_DEPTH = 3;
65
+ /** Confidence penalty applied per propagation hop (1.0 → 0.9 → 0.8 → 0.7). */
66
+ export const PROPAGATION_HOP_PENALTY = 0.1;
67
+ /**
68
+ * Confidence score for a return type inferred from `return new Constructor()` with no
69
+ * explicit TypeScript annotation. Registered as `analysis.typeInferenceConfidence` in
70
+ * `src/infrastructure/config.ts` DEFAULTS — kept in sync manually until config is
71
+ * threaded through to `extractSymbols`.
72
+ */
73
+ const INFERRED_RETURN_TYPE_CONFIDENCE = 0.85;
74
+ /**
75
+ * Extract symbols from a JS/TS parsed AST.
76
+ * When a compiled tree-sitter Query is provided (from parser.js),
77
+ * uses the fast query-based path. Falls back to manual tree walk otherwise.
78
+ */
79
+ export function extractSymbols(tree, _filePath, query) {
80
+ if (query)
81
+ return extractSymbolsQuery(tree, query);
82
+ return extractSymbolsWalk(tree);
83
+ }
84
+ // ── Query-based extraction (fast path) ──────────────────────────────────────
85
+ /** Handle function_declaration capture. */
86
+ function handleFnCapture(c, definitions) {
87
+ const fnChildren = extractParameters(c.fn_node);
88
+ definitions.push({
89
+ name: c.fn_name.text,
90
+ kind: 'function',
91
+ line: nodeStartLine(c.fn_node),
92
+ endLine: nodeEndLine(c.fn_node),
93
+ children: fnChildren.length > 0 ? fnChildren : undefined,
94
+ });
95
+ }
96
+ /** Handle variable_declarator with arrow_function / function_expression capture. */
97
+ function handleVarFnCapture(c, definitions) {
98
+ const declNode = c.varfn_name.parent?.parent;
99
+ const line = declNode ? nodeStartLine(declNode) : nodeStartLine(c.varfn_name);
100
+ const varFnChildren = extractParameters(c.varfn_value);
101
+ definitions.push({
102
+ name: c.varfn_name.text,
103
+ kind: 'function',
104
+ line,
105
+ endLine: nodeEndLine(c.varfn_value),
106
+ children: varFnChildren.length > 0 ? varFnChildren : undefined,
107
+ });
108
+ }
109
+ /** Handle class_declaration capture. */
110
+ function handleClassCapture(c, definitions, classes) {
111
+ const className = c.cls_name.text;
112
+ const startLine = nodeStartLine(c.cls_node);
113
+ const clsChildren = extractClassProperties(c.cls_node);
114
+ definitions.push({
115
+ name: className,
116
+ kind: 'class',
117
+ line: startLine,
118
+ endLine: nodeEndLine(c.cls_node),
119
+ children: clsChildren.length > 0 ? clsChildren : undefined,
120
+ });
121
+ const heritage = c.cls_node.childForFieldName('heritage') || findChild(c.cls_node, 'class_heritage');
122
+ if (heritage) {
123
+ const superName = extractSuperclass(heritage);
124
+ if (superName)
125
+ classes.push({ name: className, extends: superName, line: startLine });
126
+ const implementsList = extractImplements(heritage);
127
+ for (const iface of implementsList) {
128
+ classes.push({ name: className, implements: iface, line: startLine });
129
+ }
130
+ }
131
+ }
132
+ /** Handle method_definition capture. */
133
+ function handleMethodCapture(c, definitions) {
134
+ const methNameNode = c.meth_name;
135
+ let methName;
136
+ if (methNameNode.type === 'computed_property_name') {
137
+ // Extract the inner string literal from `['methodName']` or `["methodName"]`.
138
+ // Non-string computed keys (e.g. `[Symbol.iterator]`) cannot be resolved at
139
+ // dot-notation call sites, so skip them entirely.
140
+ const inner = methNameNode.child(1); // child(0)='[', child(1)=string, child(2)=']'
141
+ if (!inner || (inner.type !== 'string' && inner.type !== 'string_fragment'))
142
+ return;
143
+ methName = inner.text.replace(/^['"]|['"]$/g, '');
144
+ if (!methName)
145
+ return;
146
+ }
147
+ else {
148
+ methName = methNameNode.text;
149
+ }
150
+ const parentClass = findParentClass(c.meth_node);
151
+ const fullName = parentClass ? `${parentClass}.${methName}` : methName;
152
+ const methChildren = extractParameters(c.meth_node);
153
+ const methVis = extractVisibility(c.meth_node);
154
+ definitions.push({
155
+ name: fullName,
156
+ kind: 'method',
157
+ line: nodeStartLine(c.meth_node),
158
+ endLine: nodeEndLine(c.meth_node),
159
+ children: methChildren.length > 0 ? methChildren : undefined,
160
+ visibility: methVis,
161
+ });
162
+ }
163
+ /** Handle export_statement capture. */
164
+ function handleExportCapture(c, exps, imports) {
165
+ const exportLine = nodeStartLine(c.exp_node);
166
+ const decl = c.exp_node.childForFieldName('declaration');
167
+ if (decl) {
168
+ const declType = decl.type;
169
+ const kindMap = {
170
+ function_declaration: 'function',
171
+ generator_function_declaration: 'function',
172
+ class_declaration: 'class',
173
+ abstract_class_declaration: 'class',
174
+ interface_declaration: 'interface',
175
+ type_alias_declaration: 'type',
176
+ };
177
+ const kind = kindMap[declType];
178
+ if (kind) {
179
+ const n = decl.childForFieldName('name');
180
+ if (n)
181
+ exps.push({ name: n.text, kind: kind, line: exportLine });
182
+ }
183
+ }
184
+ const source = c.exp_node.childForFieldName('source') || findChild(c.exp_node, 'string');
185
+ if (source && !decl) {
186
+ const modPath = source.text.replace(/['"]/g, '');
187
+ const reexportNames = extractImportNames(c.exp_node);
188
+ const nodeText = c.exp_node.text;
189
+ const isWildcard = nodeText.includes('export *') || nodeText.includes('export*');
190
+ imports.push({
191
+ source: modPath,
192
+ names: reexportNames,
193
+ line: exportLine,
194
+ reexport: true,
195
+ wildcardReexport: isWildcard && reexportNames.length === 0,
196
+ });
197
+ }
198
+ }
199
+ function handleInterfaceCapture(c, definitions) {
200
+ const ifaceNode = c.iface_node;
201
+ const ifaceName = c.iface_name.text;
202
+ definitions.push({
203
+ name: ifaceName,
204
+ kind: 'interface',
205
+ line: nodeStartLine(ifaceNode),
206
+ endLine: nodeEndLine(ifaceNode),
207
+ });
208
+ const body = ifaceNode.childForFieldName('body') ||
209
+ findChild(ifaceNode, 'interface_body') ||
210
+ findChild(ifaceNode, 'object_type');
211
+ if (body)
212
+ extractInterfaceMethods(body, ifaceName, definitions);
213
+ }
214
+ function handleTypeCapture(c, definitions) {
215
+ const typeNode = c.type_node;
216
+ definitions.push({
217
+ name: c.type_name.text,
218
+ kind: 'type',
219
+ line: nodeStartLine(typeNode),
220
+ endLine: nodeEndLine(typeNode),
221
+ });
222
+ }
223
+ function handleImportCapture(c, imports) {
224
+ const impNode = c.imp_node;
225
+ const isTypeOnly = impNode.text.startsWith('import type');
226
+ const modPath = c.imp_source.text.replace(/['"]/g, '');
227
+ const names = extractImportNames(impNode);
228
+ imports.push({
229
+ source: modPath,
230
+ names,
231
+ line: nodeStartLine(impNode),
232
+ typeOnly: isTypeOnly,
233
+ });
234
+ }
235
+ /** Dispatch a single query match to the appropriate handler. */
236
+ function dispatchQueryMatch(c, definitions, calls, imports, classes, exps) {
237
+ if (c.fn_node) {
238
+ handleFnCapture(c, definitions);
239
+ }
240
+ else if (c.varfn_name) {
241
+ handleVarFnCapture(c, definitions);
242
+ }
243
+ else if (c.cls_node) {
244
+ handleClassCapture(c, definitions, classes);
245
+ }
246
+ else if (c.meth_node) {
247
+ handleMethodCapture(c, definitions);
248
+ }
249
+ else if (c.iface_node) {
250
+ handleInterfaceCapture(c, definitions);
251
+ }
252
+ else if (c.type_node) {
253
+ handleTypeCapture(c, definitions);
254
+ }
255
+ else if (c.imp_node) {
256
+ handleImportCapture(c, imports);
257
+ }
258
+ else if (c.exp_node) {
259
+ handleExportCapture(c, exps, imports);
260
+ }
261
+ else if (c.callfn_node) {
262
+ // Route through extractCallInfo so special identifier calls (eval) get classified.
263
+ const callfnInfo = extractCallInfo(c.callfn_name, c.callfn_node);
264
+ if (callfnInfo)
265
+ calls.push(callfnInfo);
266
+ calls.push(...extractCallbackReferenceCalls(c.callfn_node));
267
+ }
268
+ else if (c.callmem_node) {
269
+ const callInfo = extractCallInfo(c.callmem_fn, c.callmem_node);
270
+ if (callInfo)
271
+ calls.push(callInfo);
272
+ const cbDef = extractCallbackDefinition(c.callmem_node, c.callmem_fn);
273
+ if (cbDef)
274
+ definitions.push(cbDef);
275
+ calls.push(...extractCallbackReferenceCalls(c.callmem_node));
276
+ }
277
+ else if (c.callsub_node) {
278
+ const callInfo = extractCallInfo(c.callsub_fn, c.callsub_node);
279
+ if (callInfo)
280
+ calls.push(callInfo);
281
+ calls.push(...extractCallbackReferenceCalls(c.callsub_node));
282
+ }
283
+ else if (c.newfn_node) {
284
+ if (c.newfn_name.text === 'Function') {
285
+ // new Function(body) — dynamic code execution; classify as eval kind
286
+ calls.push({
287
+ name: '<dynamic:eval>',
288
+ line: nodeStartLine(c.newfn_node),
289
+ dynamic: true,
290
+ dynamicKind: 'eval',
291
+ });
292
+ }
293
+ else {
294
+ calls.push({
295
+ name: c.newfn_name.text,
296
+ line: nodeStartLine(c.newfn_node),
297
+ });
298
+ }
299
+ }
300
+ else if (c.newmem_node) {
301
+ const callInfo = extractCallInfo(c.newmem_fn, c.newmem_node);
302
+ if (callInfo)
303
+ calls.push(callInfo);
304
+ }
305
+ else if (c.assign_node) {
306
+ handleCommonJSAssignment(c.assign_left, c.assign_right, c.assign_node, imports);
307
+ handleFuncPropAssignment(c.assign_left, c.assign_right, definitions);
308
+ }
309
+ }
310
+ function extractSymbolsQuery(tree, query) {
311
+ const definitions = [];
312
+ const calls = [];
313
+ const imports = [];
314
+ const classes = [];
315
+ const exps = [];
316
+ const typeMap = new Map();
317
+ const returnTypeMap = new Map();
318
+ const callAssignments = [];
319
+ const fnRefBindings = [];
320
+ const paramBindings = [];
321
+ const arrayElemBindings = [];
322
+ const spreadArgBindings = [];
323
+ const forOfBindings = [];
324
+ const arrayCallbackBindings = [];
325
+ const objectRestParamBindings = [];
326
+ const objectPropBindings = [];
327
+ const thisCallBindings = [];
328
+ const matches = query.matches(tree.rootNode);
329
+ for (const match of matches) {
330
+ // Build capture lookup for this match (1-3 captures each, very fast)
331
+ const c = Object.create(null);
332
+ for (const cap of match.captures)
333
+ c[cap.name] = cap.node;
334
+ dispatchQueryMatch(c, definitions, calls, imports, classes, exps);
335
+ }
336
+ // Extract top-level constants via targeted walk (query patterns don't cover these)
337
+ extractConstantsWalk(tree.rootNode, definitions);
338
+ // Phase 8.2: Extract function return types first — runContextCollectorWalk's
339
+ // declarator handler reads the *complete* per-file map for inter-procedural
340
+ // propagation, so this cannot be folded into that pass.
341
+ extractReturnTypeMapWalk(tree.rootNode, returnTypeMap);
342
+ // Context-tracking collector pass: typeMap (with return-type propagation),
343
+ // object-rest param bindings, and spread/for-of/Array.from bindings.
344
+ runContextCollectorWalk(tree.rootNode, {
345
+ typeMap,
346
+ returnTypeMap,
347
+ callAssignments,
348
+ fnRefBindings,
349
+ objectRestParamBindings,
350
+ spreadArgBindings,
351
+ forOfBindings,
352
+ arrayCallbackBindings,
353
+ });
354
+ // Extract definitions from destructured bindings (query patterns don't match object_pattern)
355
+ extractDestructuredBindingsWalk(tree.rootNode, definitions);
356
+ // Everything without bespoke traversal semantics is collected in ONE pass:
357
+ // dynamic import() calls, prototype-method definitions, param bindings,
358
+ // array-element bindings, object-prop bindings, `new X()` names,
359
+ // Object.defineProperty receivers, class members (fields/static blocks,
360
+ // which query patterns don't capture), and this()/call/apply bindings.
361
+ const newExpressions = [];
362
+ const definePropertyReceivers = new Map();
363
+ runCollectorWalk(tree.rootNode, {
364
+ definitions,
365
+ typeMap,
366
+ paramBindings,
367
+ arrayElemBindings,
368
+ objectPropBindings,
369
+ newExpressions,
370
+ definePropertyReceivers,
371
+ imports,
372
+ calls,
373
+ thisCallBindings,
374
+ classMemberDefs: definitions,
375
+ });
376
+ return {
377
+ definitions,
378
+ calls,
379
+ imports,
380
+ classes,
381
+ exports: exps,
382
+ typeMap,
383
+ returnTypeMap,
384
+ callAssignments,
385
+ fnRefBindings,
386
+ paramBindings,
387
+ arrayElemBindings,
388
+ spreadArgBindings,
389
+ forOfBindings,
390
+ arrayCallbackBindings,
391
+ objectRestParamBindings,
392
+ objectPropBindings,
393
+ thisCallBindings,
394
+ newExpressions,
395
+ ...(definePropertyReceivers.size > 0 ? { definePropertyReceivers } : {}),
396
+ };
397
+ }
398
+ /** Node types that define a function scope — constants inside these are skipped. */
399
+ const FUNCTION_SCOPE_TYPES = new Set([
400
+ 'function_declaration',
401
+ 'arrow_function',
402
+ 'function_expression',
403
+ 'method_definition',
404
+ 'generator_function_declaration',
405
+ 'generator_function',
406
+ ]);
407
+ /**
408
+ * Return true when `node` has an ancestor whose type is in FUNCTION_SCOPE_TYPES.
409
+ * Used by the walk path to skip declarations inside function bodies, matching
410
+ * the query path's top-down FUNCTION_SCOPE_TYPES filter.
411
+ */
412
+ function hasFunctionScopeAncestor(node) {
413
+ let p = node.parent ?? null;
414
+ while (p) {
415
+ if (FUNCTION_SCOPE_TYPES.has(p.type))
416
+ return true;
417
+ p = p.parent ?? null;
418
+ }
419
+ return false;
420
+ }
421
+ /**
422
+ * Recursively walk the AST to extract `const x = <literal>` as constants.
423
+ * Skips nodes inside function scopes so only file-level / block-level constants
424
+ * are captured — matching the native engine's behaviour.
425
+ */
426
+ function extractConstantsWalk(node, definitions) {
427
+ for (let i = 0; i < node.childCount; i++) {
428
+ const child = node.child(i);
429
+ if (!child)
430
+ continue;
431
+ // Don't descend into function scopes
432
+ if (FUNCTION_SCOPE_TYPES.has(child.type))
433
+ continue;
434
+ let declNode = child;
435
+ // Handle `export const …` — unwrap the export_statement to its declaration child
436
+ if (child.type === 'export_statement') {
437
+ const inner = child.childForFieldName('declaration');
438
+ if (inner)
439
+ declNode = inner;
440
+ }
441
+ extractConstDeclarators(declNode, definitions);
442
+ extractLetVarObjLiteralDeclarators(declNode, definitions);
443
+ // Recurse into non-function, non-export-statement children (blocks, if-statements, etc.)
444
+ if (child.type !== 'export_statement') {
445
+ extractConstantsWalk(child, definitions);
446
+ }
447
+ }
448
+ }
449
+ // Class field definitions and static initializer blocks (which query patterns
450
+ // don't capture) are collected inline in runCollectorWalk's field_definition /
451
+ // class_static_block cases when `classMemberDefs` is set. The walk-based path
452
+ // (extractSymbolsWalk) handles these node types via walkJavaScriptNode instead.
453
+ /**
454
+ * Walk the AST to find destructured const bindings (query patterns don't match object_pattern).
455
+ * e.g. `const { handleToken, checkPermissions } = initAuth(config)`
456
+ */
457
+ function extractDestructuredBindingsWalk(node, definitions) {
458
+ for (let i = 0; i < node.childCount; i++) {
459
+ const child = node.child(i);
460
+ if (!child)
461
+ continue;
462
+ if (FUNCTION_SCOPE_TYPES.has(child.type))
463
+ continue;
464
+ let declNode = child;
465
+ if (child.type === 'export_statement') {
466
+ const inner = child.childForFieldName('declaration');
467
+ if (inner)
468
+ declNode = inner;
469
+ }
470
+ const t = declNode.type;
471
+ if ((t === 'lexical_declaration' || t === 'variable_declaration') &&
472
+ declNode.text.startsWith('const ')) {
473
+ for (let j = 0; j < declNode.childCount; j++) {
474
+ const declarator = declNode.child(j);
475
+ if (declarator?.type !== 'variable_declarator')
476
+ continue;
477
+ const nameN = declarator.childForFieldName('name');
478
+ if (nameN && nameN.type === 'object_pattern') {
479
+ extractDestructuredBindings(nameN, nodeStartLine(declNode), nodeEndLine(declNode), definitions);
480
+ }
481
+ else if (nameN && nameN.type === 'array_pattern') {
482
+ // `const [x, y] = ...` — emit a single constant node whose name is the
483
+ // full array pattern text (e.g. `[x, y]`), matching native engine behaviour.
484
+ definitions.push({
485
+ name: nameN.text,
486
+ kind: 'constant',
487
+ line: nodeStartLine(declNode),
488
+ endLine: nodeEndLine(declNode),
489
+ });
490
+ }
491
+ }
492
+ }
493
+ if (child.type !== 'export_statement') {
494
+ extractDestructuredBindingsWalk(child, definitions);
495
+ }
496
+ }
497
+ }
498
+ /** Extract constant definitions from a `const` declaration node. */
499
+ function extractConstDeclarators(declNode, definitions) {
500
+ const t = declNode.type;
501
+ if (t !== 'lexical_declaration' && t !== 'variable_declaration')
502
+ return;
503
+ if (!declNode.text.startsWith('const '))
504
+ return;
505
+ for (let j = 0; j < declNode.childCount; j++) {
506
+ const declarator = declNode.child(j);
507
+ if (declarator?.type !== 'variable_declarator')
508
+ continue;
509
+ const nameN = declarator.childForFieldName('name');
510
+ const valueN = declarator.childForFieldName('value');
511
+ if (nameN?.type !== 'identifier' || !valueN)
512
+ continue;
513
+ // Skip functions — already captured by query patterns
514
+ const valType = valueN.type;
515
+ if (valType === 'arrow_function' ||
516
+ valType === 'function_expression' ||
517
+ valType === 'function' ||
518
+ valType === 'generator_function')
519
+ continue;
520
+ if (isConstantValue(valueN)) {
521
+ definitions.push({
522
+ name: nameN.text,
523
+ kind: 'constant',
524
+ line: nodeStartLine(declNode),
525
+ endLine: nodeEndLine(declNode),
526
+ });
527
+ // Phase 8.3f: extract function/arrow properties from object literals.
528
+ // Scope guard: extractConstDeclarators is only called from extractConstantsWalk, which
529
+ // already skips const declarations inside function scopes (line ~412). So these definitions
530
+ // are always top-level. Any new call site must add a hasFunctionScopeAncestor guard
531
+ // (the walk path at handleVariableDecl does this).
532
+ if (valueN.type === 'object') {
533
+ extractObjectLiteralFunctions(valueN, nameN.text, definitions);
534
+ }
535
+ }
536
+ }
537
+ }
538
+ /**
539
+ * Extract qualified method definitions from `let`/`var` object-literal declarations.
540
+ * Mirrors `match_js_objlit_qualified_method_defs` in `javascript.rs`, which emits
541
+ * qualified definitions for `method_definition` (all declaration kinds) and
542
+ * `pair+arrow/function` (`let`/`var` only, since `const` is already handled by
543
+ * `extractConstDeclarators` → `extractObjectLiteralFunctions`).
544
+ *
545
+ * Called from extractConstantsWalk which already provides the function-scope guard.
546
+ * `var q1 = { m1() {} }` → emits Definition { name: 'q1.m1', kind: 'function' }
547
+ */
548
+ function extractLetVarObjLiteralDeclarators(declNode, definitions) {
549
+ const t = declNode.type;
550
+ if (t !== 'lexical_declaration' && t !== 'variable_declaration')
551
+ return;
552
+ if (declNode.text.startsWith('const '))
553
+ return; // handled by extractConstDeclarators
554
+ for (let j = 0; j < declNode.childCount; j++) {
555
+ const declarator = declNode.child(j);
556
+ if (declarator?.type !== 'variable_declarator')
557
+ continue;
558
+ const nameN = declarator.childForFieldName('name');
559
+ const valueN = declarator.childForFieldName('value');
560
+ if (nameN?.type !== 'identifier' || !valueN || valueN.type !== 'object')
561
+ continue;
562
+ extractObjectLiteralFunctions(valueN, nameN.text, definitions);
563
+ }
564
+ }
565
+ /**
566
+ * Recursive walk to find dynamic import() calls.
567
+ * Query patterns match call_expression with identifier/member_expression/subscript_expression
568
+ * functions, but import() has function type `import` which none of those patterns cover.
569
+ */
570
+ /**
571
+ * Collect a dynamic `import()` call at `node` (a call_expression).
572
+ * Returns true when the node *is* an import() call — the collector walk uses
573
+ * this to suppress dynamic-import collection inside the import's own argument
574
+ * subtree, preserving the former standalone walk's "don't recurse into
575
+ * import() children" behaviour without hiding those children from the other
576
+ * collectors.
577
+ */
578
+ function collectDynamicImport(node, imports) {
579
+ const fn = node.childForFieldName('function');
580
+ if (fn?.type !== 'import')
581
+ return false;
582
+ const args = node.childForFieldName('arguments') || findChild(node, 'arguments');
583
+ if (args) {
584
+ const strArg = findChild(args, 'string');
585
+ if (strArg) {
586
+ const modPath = strArg.text.replace(/['"]/g, '');
587
+ const names = extractDynamicImportNames(node);
588
+ imports.push({
589
+ source: modPath,
590
+ names,
591
+ line: nodeStartLine(node),
592
+ dynamicImport: true,
593
+ });
594
+ }
595
+ else {
596
+ debug(`Skipping non-static dynamic import() at line ${nodeStartLine(node)} (template literal or variable)`);
597
+ }
598
+ }
599
+ return true;
600
+ }
601
+ function handleCommonJSAssignment(left, right, node, imports) {
602
+ if (!left || !right)
603
+ return;
604
+ const leftText = left.text;
605
+ if (!leftText.startsWith('module.exports') && leftText !== 'exports')
606
+ return;
607
+ const assignLine = nodeStartLine(node);
608
+ // module.exports = require("…") — direct re-export
609
+ if (right.type === 'call_expression') {
610
+ extractRequireReexport(right, assignLine, imports);
611
+ }
612
+ // module.exports = { ...require("…") } — spread re-export
613
+ if (right.type === 'object') {
614
+ extractSpreadRequireReexports(right, assignLine, imports);
615
+ }
616
+ }
617
+ /** Extract a direct `require()` re-export from a call_expression. */
618
+ function extractRequireReexport(callExpr, line, imports) {
619
+ const fn = callExpr.childForFieldName('function');
620
+ const args = callExpr.childForFieldName('arguments') || findChild(callExpr, 'arguments');
621
+ if (fn && fn.text === 'require' && args) {
622
+ const strArg = findChild(args, 'string');
623
+ if (strArg) {
624
+ imports.push({
625
+ source: strArg.text.replace(/['"]/g, ''),
626
+ names: [],
627
+ line,
628
+ reexport: true,
629
+ wildcardReexport: true,
630
+ });
631
+ }
632
+ }
633
+ }
634
+ /** Extract `...require()` re-exports from spread elements inside an object literal. */
635
+ function extractSpreadRequireReexports(objectNode, line, imports) {
636
+ for (let ci = 0; ci < objectNode.childCount; ci++) {
637
+ const child = objectNode.child(ci);
638
+ if (child && child.type === 'spread_element') {
639
+ const spreadExpr = child.child(1) || child.childForFieldName('value');
640
+ if (spreadExpr && spreadExpr.type === 'call_expression') {
641
+ extractRequireReexport(spreadExpr, line, imports);
642
+ }
643
+ }
644
+ }
645
+ }
646
+ // ── Manual tree walk (fallback when Query not available) ────────────────────
647
+ function extractSymbolsWalk(tree) {
648
+ const ctx = {
649
+ definitions: [],
650
+ calls: [],
651
+ imports: [],
652
+ classes: [],
653
+ exports: [],
654
+ typeMap: new Map(),
655
+ returnTypeMap: new Map(),
656
+ callAssignments: [],
657
+ fnRefBindings: [],
658
+ paramBindings: [],
659
+ arrayElemBindings: [],
660
+ spreadArgBindings: [],
661
+ forOfBindings: [],
662
+ arrayCallbackBindings: [],
663
+ objectRestParamBindings: [],
664
+ objectPropBindings: [],
665
+ thisCallBindings: [],
666
+ };
667
+ walkJavaScriptNode(tree.rootNode, ctx);
668
+ // Phase 8.2: Extract function return types first — runContextCollectorWalk's
669
+ // declarator handler reads the *complete* per-file map for inter-procedural
670
+ // propagation, so this cannot be folded into that pass.
671
+ extractReturnTypeMapWalk(tree.rootNode, ctx.returnTypeMap);
672
+ // Context-tracking collector pass: typeMap (with return-type propagation),
673
+ // object-rest param bindings, and spread/for-of/Array.from bindings.
674
+ runContextCollectorWalk(tree.rootNode, {
675
+ typeMap: ctx.typeMap,
676
+ returnTypeMap: ctx.returnTypeMap,
677
+ callAssignments: ctx.callAssignments,
678
+ fnRefBindings: ctx.fnRefBindings,
679
+ objectRestParamBindings: ctx.objectRestParamBindings,
680
+ spreadArgBindings: ctx.spreadArgBindings,
681
+ forOfBindings: ctx.forOfBindings,
682
+ arrayCallbackBindings: ctx.arrayCallbackBindings,
683
+ });
684
+ // Single collector pass for everything else: prototype-method and func-prop
685
+ // definitions, param bindings, array-element bindings, object-prop bindings,
686
+ // `new X()` names, and Object.defineProperty receivers. Dynamic imports,
687
+ // this()/call/apply bindings, and class members are omitted here —
688
+ // walkJavaScriptNode already covers those node types on this path.
689
+ const newExpressions = [];
690
+ const definePropertyReceivers = new Map();
691
+ runCollectorWalk(tree.rootNode, {
692
+ definitions: ctx.definitions,
693
+ typeMap: ctx.typeMap,
694
+ paramBindings: ctx.paramBindings,
695
+ arrayElemBindings: ctx.arrayElemBindings,
696
+ objectPropBindings: ctx.objectPropBindings,
697
+ newExpressions,
698
+ definePropertyReceivers,
699
+ funcPropDefs: ctx.definitions,
700
+ });
701
+ ctx.newExpressions = newExpressions;
702
+ if (definePropertyReceivers.size > 0)
703
+ ctx.definePropertyReceivers = definePropertyReceivers;
704
+ return ctx;
705
+ }
706
+ function walkJavaScriptNode(node, ctx) {
707
+ switch (node.type) {
708
+ case 'function_declaration':
709
+ case 'generator_function_declaration':
710
+ handleFunctionDecl(node, ctx);
711
+ break;
712
+ case 'class_declaration':
713
+ case 'abstract_class_declaration':
714
+ // class expressions: `return class Foo extends Bar { ... }` or `const X = class Foo { ... }`
715
+ case 'class':
716
+ handleClassDecl(node, ctx);
717
+ break;
718
+ case 'class_static_block':
719
+ handleStaticBlock(node, ctx.definitions);
720
+ break;
721
+ case 'field_definition':
722
+ case 'public_field_definition':
723
+ handleFieldDef(node, ctx.definitions);
724
+ break;
725
+ case 'method_definition':
726
+ handleMethodDef(node, ctx);
727
+ break;
728
+ case 'interface_declaration':
729
+ handleInterfaceDecl(node, ctx);
730
+ break;
731
+ case 'type_alias_declaration':
732
+ handleTypeAliasDecl(node, ctx);
733
+ break;
734
+ case 'lexical_declaration':
735
+ case 'variable_declaration':
736
+ handleVariableDecl(node, ctx);
737
+ break;
738
+ case 'enum_declaration':
739
+ handleEnumDecl(node, ctx);
740
+ break;
741
+ case 'decorator':
742
+ handleDecorator(node, ctx.calls);
743
+ break;
744
+ case 'call_expression':
745
+ handleCallExpr(node, ctx);
746
+ break;
747
+ case 'new_expression':
748
+ handleNewExpr(node, ctx);
749
+ break;
750
+ case 'import_statement':
751
+ handleImportStmt(node, ctx);
752
+ break;
753
+ case 'export_statement':
754
+ handleExportStmt(node, ctx);
755
+ break;
756
+ case 'expression_statement':
757
+ handleExpressionStmt(node, ctx);
758
+ break;
759
+ }
760
+ for (let i = 0; i < node.childCount; i++) {
761
+ walkJavaScriptNode(node.child(i), ctx);
762
+ }
763
+ }
764
+ // ── Walk-path per-node-type handlers ────────────────────────────────────────
765
+ function handleFunctionDecl(node, ctx) {
766
+ const nameNode = node.childForFieldName('name');
767
+ if (nameNode) {
768
+ const fnChildren = extractParameters(node);
769
+ ctx.definitions.push({
770
+ name: nameNode.text,
771
+ kind: 'function',
772
+ line: nodeStartLine(node),
773
+ endLine: nodeEndLine(node),
774
+ children: fnChildren.length > 0 ? fnChildren : undefined,
775
+ });
776
+ }
777
+ }
778
+ function handleClassDecl(node, ctx) {
779
+ const nameNode = node.childForFieldName('name');
780
+ if (!nameNode)
781
+ return;
782
+ const className = nameNode.text;
783
+ const startLine = nodeStartLine(node);
784
+ const clsChildren = extractClassProperties(node);
785
+ ctx.definitions.push({
786
+ name: className,
787
+ kind: 'class',
788
+ line: startLine,
789
+ endLine: nodeEndLine(node),
790
+ children: clsChildren.length > 0 ? clsChildren : undefined,
791
+ });
792
+ const heritage = node.childForFieldName('heritage') || findChild(node, 'class_heritage');
793
+ if (heritage) {
794
+ const superName = extractSuperclass(heritage);
795
+ if (superName) {
796
+ ctx.classes.push({ name: className, extends: superName, line: startLine });
797
+ }
798
+ const implementsList = extractImplements(heritage);
799
+ for (const iface of implementsList) {
800
+ ctx.classes.push({ name: className, implements: iface, line: startLine });
801
+ }
802
+ }
803
+ }
804
+ function handleMethodDef(node, ctx) {
805
+ const nameNode = node.childForFieldName('name');
806
+ if (nameNode) {
807
+ let methName;
808
+ if (nameNode.type === 'computed_property_name') {
809
+ // Extract the inner string literal from `['methodName']` or `["methodName"]`.
810
+ // Non-string computed keys (e.g. `[Symbol.iterator]`) cannot be resolved at
811
+ // dot-notation call sites, so skip them entirely.
812
+ const inner = nameNode.child(1); // child(0)='[', child(1)=string, child(2)=']'
813
+ if (!inner || (inner.type !== 'string' && inner.type !== 'string_fragment'))
814
+ return;
815
+ methName = inner.text.replace(/^['"]|['"]$/g, '');
816
+ if (!methName)
817
+ return;
818
+ }
819
+ else {
820
+ methName = nameNode.text;
821
+ }
822
+ const parentClass = findParentClass(node);
823
+ const fullName = parentClass ? `${parentClass}.${methName}` : methName;
824
+ const methChildren = extractParameters(node);
825
+ const methVis = extractVisibility(node);
826
+ ctx.definitions.push({
827
+ name: fullName,
828
+ kind: 'method',
829
+ line: nodeStartLine(node),
830
+ endLine: nodeEndLine(node),
831
+ children: methChildren.length > 0 ? methChildren : undefined,
832
+ visibility: methVis,
833
+ });
834
+ }
835
+ }
836
+ /**
837
+ * Create a synthetic `ClassName.<static:L:C>` definition for a class static block
838
+ * so that calls inside the block can be attributed to a method-kind node and
839
+ * `resolveThisDispatch` can walk up to the parent class for `super.method()`.
840
+ *
841
+ * The start line and column are appended to the name to ensure uniqueness when a
842
+ * class has multiple `static { }` blocks (each has a distinct start position even
843
+ * if on the same line).
844
+ *
845
+ * Tree-sitter uses `class_static_block` (not `static_block`) for `static { ... }`.
846
+ */
847
+ function handleStaticBlock(node, definitions) {
848
+ const parentClass = findParentClass(node);
849
+ if (!parentClass)
850
+ return;
851
+ const line = nodeStartLine(node);
852
+ const col = node.startPosition.column;
853
+ definitions.push({
854
+ name: `${parentClass}.<static:${line}:${col}>`,
855
+ kind: 'method',
856
+ line,
857
+ endLine: nodeEndLine(node),
858
+ });
859
+ }
860
+ /**
861
+ * Emit a `ClassName.fieldName` definition for class fields that have an initializer.
862
+ * This lets `findCaller` attribute calls inside field initializers (e.g. static field
863
+ * side-effects) to the field rather than the enclosing class.
864
+ *
865
+ * JS `field_definition` uses the `'property'` field name; TS
866
+ * `public_field_definition` uses `'name'`. As a third fallback (Rust/TS parity) we
867
+ * also check for a positional `property_identifier` child.
868
+ */
869
+ const CALLABLE_FIELD_TYPES = new Set([
870
+ 'arrow_function',
871
+ 'function_expression',
872
+ 'generator_function',
873
+ ]);
874
+ function handleFieldDef(node, definitions) {
875
+ // JS field_definition uses 'property' field; TS public_field_definition uses 'name' field
876
+ const nameNode = node.childForFieldName('name') ||
877
+ node.childForFieldName('property') ||
878
+ findChild(node, 'property_identifier');
879
+ const valueNode = node.childForFieldName('value');
880
+ if (!nameNode || !valueNode)
881
+ return;
882
+ if (nameNode.type === 'computed_property_name')
883
+ return;
884
+ // Only emit a callable definition when the initializer is a function/arrow expression.
885
+ // Scalar fields like `static x = 42` should not appear as method-kind nodes.
886
+ if (!CALLABLE_FIELD_TYPES.has(valueNode.type))
887
+ return;
888
+ const fieldName = nameNode.text;
889
+ if (!fieldName)
890
+ return;
891
+ const parentClass = findParentClass(node);
892
+ if (!parentClass)
893
+ return;
894
+ definitions.push({
895
+ name: `${parentClass}.${fieldName}`,
896
+ kind: 'method',
897
+ line: nodeStartLine(node),
898
+ endLine: nodeEndLine(node),
899
+ });
900
+ }
901
+ function handleInterfaceDecl(node, ctx) {
902
+ const nameNode = node.childForFieldName('name');
903
+ if (!nameNode)
904
+ return;
905
+ ctx.definitions.push({
906
+ name: nameNode.text,
907
+ kind: 'interface',
908
+ line: nodeStartLine(node),
909
+ endLine: nodeEndLine(node),
910
+ });
911
+ const body = node.childForFieldName('body') ||
912
+ findChild(node, 'interface_body') ||
913
+ findChild(node, 'object_type');
914
+ if (body) {
915
+ extractInterfaceMethods(body, nameNode.text, ctx.definitions);
916
+ }
917
+ }
918
+ function handleTypeAliasDecl(node, ctx) {
919
+ const nameNode = node.childForFieldName('name');
920
+ if (nameNode) {
921
+ ctx.definitions.push({
922
+ name: nameNode.text,
923
+ kind: 'type',
924
+ line: nodeStartLine(node),
925
+ endLine: nodeEndLine(node),
926
+ });
927
+ }
928
+ }
929
+ /**
930
+ * Extract definitions from destructured object bindings.
931
+ * `const { handleToken, checkPermissions } = initAuth(...)` creates definitions
932
+ * for handleToken and checkPermissions so they can be resolved as call targets.
933
+ */
934
+ function extractDestructuredBindings(pattern, line, endLine, definitions) {
935
+ for (let i = 0; i < pattern.childCount; i++) {
936
+ const child = pattern.child(i);
937
+ if (!child)
938
+ continue;
939
+ if (child.type === 'shorthand_property_identifier_pattern' ||
940
+ child.type === 'shorthand_property_identifier') {
941
+ // { handleToken } — shorthand binding
942
+ definitions.push({ name: child.text, kind: 'function', line, endLine });
943
+ }
944
+ else if (child.type === 'pair_pattern' || child.type === 'pair') {
945
+ // { original: renamed } — renamed binding, use the local alias
946
+ const value = child.childForFieldName('value');
947
+ if (value &&
948
+ (value.type === 'identifier' || value.type === 'shorthand_property_identifier_pattern')) {
949
+ definitions.push({ name: value.text, kind: 'function', line, endLine });
950
+ }
951
+ }
952
+ }
953
+ }
954
+ function handleVariableDecl(node, ctx) {
955
+ const isConst = node.text.startsWith('const ');
956
+ for (let i = 0; i < node.childCount; i++) {
957
+ const declarator = node.child(i);
958
+ if (declarator && declarator.type === 'variable_declarator') {
959
+ const nameN = declarator.childForFieldName('name');
960
+ const valueN = declarator.childForFieldName('value');
961
+ if (nameN && valueN) {
962
+ const valType = valueN.type;
963
+ if (valType === 'arrow_function' ||
964
+ valType === 'function_expression' ||
965
+ valType === 'function' ||
966
+ valType === 'generator_function') {
967
+ const varFnChildren = extractParameters(valueN);
968
+ ctx.definitions.push({
969
+ name: nameN.text,
970
+ kind: 'function',
971
+ line: nodeStartLine(node),
972
+ endLine: nodeEndLine(valueN),
973
+ children: varFnChildren.length > 0 ? varFnChildren : undefined,
974
+ });
975
+ }
976
+ else if (isConst &&
977
+ nameN.type === 'identifier' &&
978
+ isConstantValue(valueN) &&
979
+ !hasFunctionScopeAncestor(node)) {
980
+ ctx.definitions.push({
981
+ name: nameN.text,
982
+ kind: 'constant',
983
+ line: nodeStartLine(node),
984
+ endLine: nodeEndLine(node),
985
+ });
986
+ // Phase 8.3f: extract function/arrow properties from object literals so that
987
+ // this.method() calls inside Object.defineProperty accessors can resolve them.
988
+ // Scope guard: hasFunctionScopeAncestor mirrors the Rust path's find_parent_of_types
989
+ // check and the sibling destructured-binding branch below — skips object literals
990
+ // inside function bodies to avoid polluting the global definition index with
991
+ // local variable properties (e.g. `localObj.fn` from `const localObj = { fn: ... }`
992
+ // inside a function).
993
+ if (valueN.type === 'object') {
994
+ extractObjectLiteralFunctions(valueN, nameN.text, ctx.definitions);
995
+ }
996
+ }
997
+ else if (!isConst &&
998
+ nameN.type === 'identifier' &&
999
+ valueN.type === 'object' &&
1000
+ !hasFunctionScopeAncestor(node)) {
1001
+ // `let`/`var` object literals: extract qualified method definitions so that
1002
+ // `obj.method()` calls resolve correctly. Mirrors Rust match_js_objlit_qualified_method_defs
1003
+ // which emits method_definition qualified names for ALL declaration kinds and
1004
+ // pair+arrow/function for let/var only (const is already handled above).
1005
+ // Scope guard prevents local object properties from polluting the global index.
1006
+ extractObjectLiteralFunctions(valueN, nameN.text, ctx.definitions);
1007
+ }
1008
+ else if (isConst && nameN.type === 'object_pattern' && !hasFunctionScopeAncestor(node)) {
1009
+ // Destructured bindings: const { handleToken, checkPermissions } = initAuth(...)
1010
+ // Each destructured property becomes a function definition so it can be
1011
+ // resolved when passed as a callback (e.g. router.use(handleToken)).
1012
+ // Restricted to const to avoid creating spurious definitions for
1013
+ // transient let/var destructuring (e.g. let { userId } = parseRequest(req)).
1014
+ // Scope guard mirrors extractDestructuredBindingsWalk (query path) and
1015
+ // handle_var_decl (Rust path) — skips bindings inside function bodies.
1016
+ extractDestructuredBindings(nameN, nodeStartLine(node), nodeEndLine(node), ctx.definitions);
1017
+ }
1018
+ else if (isConst && nameN.type === 'array_pattern' && !hasFunctionScopeAncestor(node)) {
1019
+ // Array destructuring: `const [x, y] = ...` — emit a single constant node
1020
+ // whose name is the full array pattern text (e.g. `[x, y]`), matching
1021
+ // native engine behaviour. Scope guard mirrors the object_pattern branch above.
1022
+ ctx.definitions.push({
1023
+ name: nameN.text,
1024
+ kind: 'constant',
1025
+ line: nodeStartLine(node),
1026
+ endLine: nodeEndLine(node),
1027
+ });
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1032
+ }
1033
+ /**
1034
+ * Phase 8.3f: extract function/arrow function properties from an object literal as standalone
1035
+ * definitions so that `this.method()` calls inside Object.defineProperty accessor functions can
1036
+ * resolve them via the same-file definition lookup.
1037
+ *
1038
+ * Definitions are emitted as qualified names (`obj.baz` rather than bare `baz`) to avoid
1039
+ * polluting the global definition index with common property names like `init`, `run`, or
1040
+ * `render`. The typeMap value stored by the caller also uses the qualified name so the resolver
1041
+ * looks up `lookup.byName('obj.baz')` rather than `lookup.byName('baz')`.
1042
+ *
1043
+ * `const obj = { baz: () => {} }` → emits Definition { name: 'obj.baz', kind: 'function' }
1044
+ */
1045
+ function extractObjectLiteralFunctions(objNode, varName, definitions) {
1046
+ for (let i = 0; i < objNode.childCount; i++) {
1047
+ const child = objNode.child(i);
1048
+ if (!child)
1049
+ continue;
1050
+ if (child.type === 'pair') {
1051
+ const keyNode = child.childForFieldName('key');
1052
+ const valueNode = child.childForFieldName('value');
1053
+ if (!keyNode || !valueNode)
1054
+ continue;
1055
+ const keyName = keyNode.type === 'string' ? keyNode.text.replace(/^['"]|['"]$/g, '') : keyNode.text;
1056
+ if (!keyName)
1057
+ continue;
1058
+ if (valueNode.type === 'arrow_function' ||
1059
+ valueNode.type === 'function_expression' ||
1060
+ valueNode.type === 'function') {
1061
+ definitions.push({
1062
+ name: `${varName}.${keyName}`,
1063
+ kind: 'function',
1064
+ line: nodeStartLine(child),
1065
+ endLine: nodeEndLine(valueNode),
1066
+ });
1067
+ }
1068
+ }
1069
+ else if (child.type === 'method_definition') {
1070
+ const nameNode = child.childForFieldName('name');
1071
+ if (nameNode) {
1072
+ let methodName;
1073
+ if (nameNode.type === 'computed_property_name') {
1074
+ // Strip brackets+quotes from `['methodName']` to get a resolvable name.
1075
+ // Skip non-string computed keys (e.g. [Symbol.iterator]).
1076
+ const inner = nameNode.child(1);
1077
+ if (!inner || (inner.type !== 'string' && inner.type !== 'string_fragment'))
1078
+ continue;
1079
+ methodName = inner.text.replace(/^['"]|['"]$/g, '');
1080
+ if (!methodName)
1081
+ continue;
1082
+ }
1083
+ else {
1084
+ methodName = nameNode.text;
1085
+ }
1086
+ definitions.push({
1087
+ name: `${varName}.${methodName}`,
1088
+ kind: 'function',
1089
+ line: nodeStartLine(child),
1090
+ endLine: nodeEndLine(child),
1091
+ });
1092
+ }
1093
+ }
1094
+ }
1095
+ }
1096
+ function handleEnumDecl(node, ctx) {
1097
+ const nameNode = node.childForFieldName('name');
1098
+ if (!nameNode)
1099
+ return;
1100
+ const enumChildren = [];
1101
+ const body = node.childForFieldName('body') || findChild(node, 'enum_body');
1102
+ if (body) {
1103
+ for (let i = 0; i < body.childCount; i++) {
1104
+ const member = body.child(i);
1105
+ if (!member)
1106
+ continue;
1107
+ if (member.type === 'enum_assignment' || member.type === 'property_identifier') {
1108
+ const mName = member.childForFieldName('name') || member.child(0);
1109
+ if (mName) {
1110
+ enumChildren.push({
1111
+ name: mName.text,
1112
+ kind: 'constant',
1113
+ line: nodeStartLine(member),
1114
+ });
1115
+ }
1116
+ }
1117
+ }
1118
+ }
1119
+ ctx.definitions.push({
1120
+ name: nameNode.text,
1121
+ kind: 'enum',
1122
+ line: nodeStartLine(node),
1123
+ endLine: nodeEndLine(node),
1124
+ children: enumChildren.length > 0 ? enumChildren : undefined,
1125
+ });
1126
+ }
1127
+ function handleCallExpr(node, ctx) {
1128
+ const fn = node.childForFieldName('function');
1129
+ if (!fn)
1130
+ return;
1131
+ if (fn.type === 'import') {
1132
+ handleDynamicImportCall(node, ctx.imports);
1133
+ }
1134
+ else {
1135
+ // this() calls: `this` used as a function (not as a receiver).
1136
+ if (fn.type === 'this') {
1137
+ ctx.calls.push({ name: 'this', line: nodeStartLine(node) });
1138
+ return; // no further processing needed for this()-style calls
1139
+ }
1140
+ const callInfo = extractCallInfo(fn, node);
1141
+ if (callInfo)
1142
+ ctx.calls.push(callInfo);
1143
+ if (fn.type === 'member_expression') {
1144
+ const cbDef = extractCallbackDefinition(node, fn);
1145
+ if (cbDef)
1146
+ ctx.definitions.push(cbDef);
1147
+ // this-call bindings: `fn.call(namedCtx, ...)` / `fn.apply(namedCtx, ...)`
1148
+ const obj = fn.childForFieldName('object');
1149
+ const prop = fn.childForFieldName('property');
1150
+ if (obj?.type === 'identifier' &&
1151
+ prop &&
1152
+ (prop.text === 'call' || prop.text === 'apply') &&
1153
+ !BUILTIN_GLOBALS.has(obj.text)) {
1154
+ const args = node.childForFieldName('arguments') || findChild(node, 'arguments');
1155
+ if (args) {
1156
+ for (let i = 0; i < args.childCount; i++) {
1157
+ const child = args.child(i);
1158
+ if (!child)
1159
+ continue;
1160
+ const t = child.type;
1161
+ if (t === '(' || t === ')' || t === ',')
1162
+ continue;
1163
+ if (t === 'identifier' &&
1164
+ !BUILTIN_GLOBALS.has(child.text) &&
1165
+ child.text !== 'undefined' &&
1166
+ child.text !== 'null') {
1167
+ ctx.thisCallBindings.push({ callee: obj.text, thisArg: child.text });
1168
+ }
1169
+ break;
1170
+ }
1171
+ }
1172
+ }
1173
+ }
1174
+ ctx.calls.push(...extractCallbackReferenceCalls(node));
1175
+ }
1176
+ }
1177
+ function handleNewExpr(node, ctx) {
1178
+ const ctor = node.childForFieldName('constructor') || node.child(1);
1179
+ if (!ctor)
1180
+ return;
1181
+ if (ctor.type === 'identifier') {
1182
+ if (ctor.text === 'Function') {
1183
+ // new Function(body) — dynamic code execution; undecidable static target
1184
+ ctx.calls.push({
1185
+ name: '<dynamic:eval>',
1186
+ line: nodeStartLine(node),
1187
+ dynamic: true,
1188
+ dynamicKind: 'eval',
1189
+ });
1190
+ }
1191
+ else {
1192
+ ctx.calls.push({ name: ctor.text, line: nodeStartLine(node) });
1193
+ }
1194
+ }
1195
+ else if (ctor.type === 'member_expression') {
1196
+ const callInfo = extractCallInfo(ctor, node);
1197
+ if (callInfo)
1198
+ ctx.calls.push(callInfo);
1199
+ }
1200
+ }
1201
+ /**
1202
+ * Handle a TypeScript/JS decorator node.
1203
+ *
1204
+ * Only handles bare-identifier and bare-member-expression decorators
1205
+ * (`@Foo`, `@Foo.bar`) since decorated call expressions (`@Foo()`, `@Foo.bar()`)
1206
+ * are already visited as `call_expression` children by the recursive walker.
1207
+ */
1208
+ function handleDecorator(node, calls) {
1209
+ // Decorators wrap their expression; find the first non-@ child
1210
+ for (let i = 0; i < node.childCount; i++) {
1211
+ const child = node.child(i);
1212
+ if (!child || child.type === '@')
1213
+ continue;
1214
+ const t = child.type;
1215
+ if (t === 'identifier') {
1216
+ // @Foo — the identifier is the decorator factory; emit as reflection call
1217
+ calls.push({
1218
+ name: child.text,
1219
+ line: nodeStartLine(node),
1220
+ dynamic: true,
1221
+ dynamicKind: 'reflection',
1222
+ });
1223
+ }
1224
+ else if (t === 'member_expression') {
1225
+ // @Foo.bar — emit as reflection; always mark dynamic since it's decorator dispatch
1226
+ const callInfo = extractCallInfo(child, node);
1227
+ if (callInfo)
1228
+ calls.push({ ...callInfo, dynamic: true, dynamicKind: 'reflection' });
1229
+ }
1230
+ // call_expression / other — handled by the recursive walker automatically
1231
+ break;
1232
+ }
1233
+ }
1234
+ /** Handle a dynamic import() call expression and add to imports if static. */
1235
+ function handleDynamicImportCall(node, imports) {
1236
+ const args = node.childForFieldName('arguments') || findChild(node, 'arguments');
1237
+ if (!args)
1238
+ return;
1239
+ const strArg = findChild(args, 'string');
1240
+ if (strArg) {
1241
+ const modPath = strArg.text.replace(/['"]/g, '');
1242
+ const names = extractDynamicImportNames(node);
1243
+ imports.push({ source: modPath, names, line: nodeStartLine(node), dynamicImport: true });
1244
+ }
1245
+ else {
1246
+ debug(`Skipping non-static dynamic import() at line ${nodeStartLine(node)} (template literal or variable)`);
1247
+ }
1248
+ }
1249
+ function handleImportStmt(node, ctx) {
1250
+ const isTypeOnly = node.text.startsWith('import type');
1251
+ const source = node.childForFieldName('source') || findChild(node, 'string');
1252
+ if (source) {
1253
+ const modPath = source.text.replace(/['"]/g, '');
1254
+ const names = extractImportNames(node);
1255
+ ctx.imports.push({
1256
+ source: modPath,
1257
+ names,
1258
+ line: nodeStartLine(node),
1259
+ typeOnly: isTypeOnly,
1260
+ });
1261
+ }
1262
+ }
1263
+ function handleExportStmt(node, ctx) {
1264
+ const exportLine = nodeStartLine(node);
1265
+ const decl = node.childForFieldName('declaration');
1266
+ if (decl) {
1267
+ const declType = decl.type;
1268
+ const kindMap = {
1269
+ function_declaration: 'function',
1270
+ generator_function_declaration: 'function',
1271
+ class_declaration: 'class',
1272
+ abstract_class_declaration: 'class',
1273
+ interface_declaration: 'interface',
1274
+ type_alias_declaration: 'type',
1275
+ };
1276
+ const kind = kindMap[declType];
1277
+ if (kind) {
1278
+ const n = decl.childForFieldName('name');
1279
+ if (n)
1280
+ ctx.exports.push({ name: n.text, kind: kind, line: exportLine });
1281
+ }
1282
+ }
1283
+ const source = node.childForFieldName('source') || findChild(node, 'string');
1284
+ if (source && !decl) {
1285
+ const modPath = source.text.replace(/['"]/g, '');
1286
+ const reexportNames = extractImportNames(node);
1287
+ const nodeText = node.text;
1288
+ const isWildcard = nodeText.includes('export *') || nodeText.includes('export*');
1289
+ ctx.imports.push({
1290
+ source: modPath,
1291
+ names: reexportNames,
1292
+ line: exportLine,
1293
+ reexport: true,
1294
+ wildcardReexport: isWildcard && reexportNames.length === 0,
1295
+ });
1296
+ }
1297
+ }
1298
+ function handleExpressionStmt(node, ctx) {
1299
+ const expr = node.child(0);
1300
+ if (expr && expr.type === 'assignment_expression') {
1301
+ const left = expr.childForFieldName('left');
1302
+ const right = expr.childForFieldName('right');
1303
+ if (left && right)
1304
+ handleCommonJSAssignment(left, right, node, ctx.imports);
1305
+ }
1306
+ }
1307
+ // ── Child extraction helpers ────────────────────────────────────────────────
1308
+ function extractParameters(node) {
1309
+ const params = [];
1310
+ const paramsNode = node.childForFieldName('parameters') || findChild(node, 'formal_parameters');
1311
+ if (!paramsNode)
1312
+ return params;
1313
+ for (let i = 0; i < paramsNode.childCount; i++) {
1314
+ const child = paramsNode.child(i);
1315
+ if (!child)
1316
+ continue;
1317
+ const t = child.type;
1318
+ if (t === 'identifier') {
1319
+ params.push({ name: child.text, kind: 'parameter', line: nodeStartLine(child) });
1320
+ }
1321
+ else if (t === 'required_parameter' ||
1322
+ t === 'optional_parameter' ||
1323
+ t === 'assignment_pattern') {
1324
+ const nameNode = child.childForFieldName('pattern') || child.childForFieldName('left') || child.child(0);
1325
+ if (nameNode &&
1326
+ (nameNode.type === 'identifier' ||
1327
+ nameNode.type === 'shorthand_property_identifier_pattern')) {
1328
+ params.push({ name: nameNode.text, kind: 'parameter', line: nodeStartLine(child) });
1329
+ }
1330
+ }
1331
+ else if (t === 'rest_pattern' || t === 'rest_element') {
1332
+ const nameNode = child.child(1) || child.childForFieldName('name');
1333
+ if (nameNode && nameNode.type === 'identifier') {
1334
+ params.push({ name: nameNode.text, kind: 'parameter', line: nodeStartLine(child) });
1335
+ }
1336
+ }
1337
+ }
1338
+ return params;
1339
+ }
1340
+ function extractClassProperties(classNode) {
1341
+ const props = [];
1342
+ const body = classNode.childForFieldName('body') || findChild(classNode, 'class_body');
1343
+ if (!body)
1344
+ return props;
1345
+ for (let i = 0; i < body.childCount; i++) {
1346
+ const child = body.child(i);
1347
+ if (!child)
1348
+ continue;
1349
+ if (child.type === 'field_definition' ||
1350
+ child.type === 'public_field_definition' ||
1351
+ child.type === 'property_definition') {
1352
+ const nameNode = child.childForFieldName('name') || child.childForFieldName('property') || child.child(0);
1353
+ if (nameNode &&
1354
+ (nameNode.type === 'property_identifier' ||
1355
+ nameNode.type === 'identifier' ||
1356
+ nameNode.type === 'private_property_identifier')) {
1357
+ // Private # fields: nameNode.type is 'private_property_identifier'
1358
+ // TS modifiers: accessibility_modifier child on the field_definition
1359
+ const vis = nameNode.type === 'private_property_identifier' ? 'private' : extractVisibility(child);
1360
+ props.push({
1361
+ name: nameNode.text,
1362
+ kind: 'property',
1363
+ line: nodeStartLine(child),
1364
+ visibility: vis,
1365
+ });
1366
+ }
1367
+ }
1368
+ }
1369
+ return props;
1370
+ }
1371
+ /**
1372
+ * Extract visibility modifier from a class member node.
1373
+ * Checks for TS access modifiers (public/private/protected) and JS private (#) fields.
1374
+ * Returns 'public' | 'private' | 'protected' | undefined.
1375
+ */
1376
+ function extractVisibility(node) {
1377
+ // Check for TS accessibility modifiers (accessibility_modifier child)
1378
+ for (let i = 0; i < node.childCount; i++) {
1379
+ const child = node.child(i);
1380
+ if (!child)
1381
+ continue;
1382
+ if (child.type === 'accessibility_modifier') {
1383
+ const text = child.text;
1384
+ if (text === 'private' || text === 'protected' || text === 'public')
1385
+ return text;
1386
+ }
1387
+ }
1388
+ // Check for JS private name (# prefix) — try multiple field names
1389
+ const nameNode = node.childForFieldName('name') || node.childForFieldName('property') || node.child(0);
1390
+ if (nameNode && nameNode.type === 'private_property_identifier') {
1391
+ return 'private';
1392
+ }
1393
+ return undefined;
1394
+ }
1395
+ function isConstantValue(valueNode) {
1396
+ if (!valueNode)
1397
+ return false;
1398
+ const t = valueNode.type;
1399
+ return (t === 'number' ||
1400
+ t === 'string' ||
1401
+ t === 'template_string' ||
1402
+ t === 'true' ||
1403
+ t === 'false' ||
1404
+ t === 'null' ||
1405
+ t === 'undefined' ||
1406
+ t === 'array' ||
1407
+ t === 'object' ||
1408
+ t === 'regex' ||
1409
+ t === 'unary_expression' ||
1410
+ t === 'binary_expression' ||
1411
+ t === 'new_expression');
1412
+ }
1413
+ // ── Shared helpers ──────────────────────────────────────────────────────────
1414
+ function extractInterfaceMethods(bodyNode, interfaceName, definitions) {
1415
+ for (let i = 0; i < bodyNode.childCount; i++) {
1416
+ const child = bodyNode.child(i);
1417
+ if (!child)
1418
+ continue;
1419
+ if (child.type === 'method_signature' || child.type === 'property_signature') {
1420
+ const nameNode = child.childForFieldName('name');
1421
+ if (nameNode) {
1422
+ definitions.push({
1423
+ name: `${interfaceName}.${nameNode.text}`,
1424
+ kind: 'method',
1425
+ line: nodeStartLine(child),
1426
+ endLine: nodeEndLine(child),
1427
+ });
1428
+ }
1429
+ }
1430
+ }
1431
+ }
1432
+ function extractImplements(heritage) {
1433
+ const interfaces = [];
1434
+ for (let i = 0; i < heritage.childCount; i++) {
1435
+ const child = heritage.child(i);
1436
+ if (!child)
1437
+ continue;
1438
+ if (child.text === 'implements') {
1439
+ for (let j = i + 1; j < heritage.childCount; j++) {
1440
+ const next = heritage.child(j);
1441
+ if (!next)
1442
+ continue;
1443
+ if (next.type === 'identifier')
1444
+ interfaces.push(next.text);
1445
+ else if (next.type === 'type_identifier')
1446
+ interfaces.push(next.text);
1447
+ if (next.childCount > 0)
1448
+ interfaces.push(...extractImplementsFromNode(next));
1449
+ }
1450
+ break;
1451
+ }
1452
+ if (child.type === 'implements_clause') {
1453
+ interfaces.push(...extractImplementsFromNode(child));
1454
+ }
1455
+ }
1456
+ return interfaces;
1457
+ }
1458
+ function extractImplementsFromNode(node) {
1459
+ const result = [];
1460
+ for (let i = 0; i < node.childCount; i++) {
1461
+ const child = node.child(i);
1462
+ if (!child)
1463
+ continue;
1464
+ if (child.type === 'identifier' || child.type === 'type_identifier')
1465
+ result.push(child.text);
1466
+ if (child.childCount > 0)
1467
+ result.push(...extractImplementsFromNode(child));
1468
+ }
1469
+ return result;
1470
+ }
1471
+ // ── Type inference helpers ───────────────────────────────────────────────
1472
+ function extractSimpleTypeName(typeAnnotationNode) {
1473
+ if (!typeAnnotationNode)
1474
+ return null;
1475
+ for (let i = 0; i < typeAnnotationNode.childCount; i++) {
1476
+ const child = typeAnnotationNode.child(i);
1477
+ if (!child)
1478
+ continue;
1479
+ const t = child.type;
1480
+ if (t === 'type_identifier' || t === 'identifier')
1481
+ return child.text;
1482
+ if (t === 'generic_type')
1483
+ return child.child(0)?.text || null;
1484
+ if (t === 'parenthesized_type')
1485
+ return extractSimpleTypeName(child);
1486
+ // Skip union, intersection, and array types — too ambiguous
1487
+ }
1488
+ return null;
1489
+ }
1490
+ function extractNewExprTypeName(newExprNode) {
1491
+ if (newExprNode?.type !== 'new_expression')
1492
+ return null;
1493
+ const ctor = newExprNode.childForFieldName('constructor') || newExprNode.child(1);
1494
+ if (!ctor)
1495
+ return null;
1496
+ if (ctor.type === 'identifier')
1497
+ return ctor.text;
1498
+ if (ctor.type === 'member_expression') {
1499
+ const prop = ctor.childForFieldName('property');
1500
+ return prop ? prop.text : null;
1501
+ }
1502
+ return null;
1503
+ }
1504
+ // ── Phase 8.2: Inter-Procedural Return Type Propagation ─────────────────────
1505
+ /**
1506
+ * Walk the AST and record the return type of every function/method definition.
1507
+ *
1508
+ * Keys: plain name (e.g. "createUser") or "ClassName.methodName" for methods.
1509
+ * Confidence:
1510
+ * - 1.0: explicit TypeScript return type annotation
1511
+ * - 0.85: inferred from the first `return new Constructor()` in the body
1512
+ */
1513
+ function extractReturnTypeMapWalk(rootNode, returnTypeMap) {
1514
+ function walk(node, depth, currentClass) {
1515
+ if (depth >= MAX_WALK_DEPTH)
1516
+ return;
1517
+ const t = node.type;
1518
+ if (t === 'class_declaration' || t === 'abstract_class_declaration' || t === 'class') {
1519
+ const nameNode = node.childForFieldName('name');
1520
+ const className = nameNode?.text ?? null;
1521
+ for (let i = 0; i < node.childCount; i++) {
1522
+ walk(node.child(i), depth + 1, className);
1523
+ }
1524
+ return;
1525
+ }
1526
+ if (t === 'function_declaration' || t === 'generator_function_declaration') {
1527
+ const nameNode = node.childForFieldName('name');
1528
+ if (nameNode?.type === 'identifier' && nameNode.text !== 'constructor') {
1529
+ const fnName = currentClass ? `${currentClass}.${nameNode.text}` : nameNode.text;
1530
+ storeReturnType(node, fnName, returnTypeMap);
1531
+ }
1532
+ // Recurse into the function body with null currentClass so nested
1533
+ // function declarations are not stored under the enclosing class name.
1534
+ for (let i = 0; i < node.childCount; i++) {
1535
+ walk(node.child(i), depth + 1, null);
1536
+ }
1537
+ return;
1538
+ }
1539
+ else if (t === 'method_definition') {
1540
+ const nameNode = node.childForFieldName('name');
1541
+ if (nameNode && currentClass && nameNode.text !== 'constructor') {
1542
+ storeReturnType(node, `${currentClass}.${nameNode.text}`, returnTypeMap);
1543
+ }
1544
+ // Recurse into the method body with null currentClass so nested
1545
+ // function declarations are not stored under the enclosing class name.
1546
+ for (let i = 0; i < node.childCount; i++) {
1547
+ walk(node.child(i), depth + 1, null);
1548
+ }
1549
+ return;
1550
+ }
1551
+ else if (t === 'variable_declarator') {
1552
+ // const foo = (): ReturnType => … or const foo = function(): ReturnType { … }
1553
+ const nameN = node.childForFieldName('name');
1554
+ const valueN = node.childForFieldName('value');
1555
+ if (nameN?.type === 'identifier' && valueN) {
1556
+ const vt = valueN.type;
1557
+ if (vt === 'arrow_function' ||
1558
+ vt === 'function_expression' ||
1559
+ vt === 'generator_function') {
1560
+ const fnName = currentClass ? `${currentClass}.${nameN.text}` : nameN.text;
1561
+ storeReturnType(valueN, fnName, returnTypeMap);
1562
+ }
1563
+ }
1564
+ }
1565
+ for (let i = 0; i < node.childCount; i++) {
1566
+ walk(node.child(i), depth + 1, currentClass);
1567
+ }
1568
+ }
1569
+ walk(rootNode, 0, null);
1570
+ }
1571
+ /** Extract the return type of a function node and store it in the returnTypeMap. */
1572
+ function storeReturnType(fnNode, fnName, returnTypeMap) {
1573
+ const returnTypeNode = fnNode.childForFieldName('return_type');
1574
+ if (returnTypeNode) {
1575
+ const typeName = extractSimpleTypeName(returnTypeNode);
1576
+ if (typeName) {
1577
+ const existing = returnTypeMap.get(fnName);
1578
+ if (!existing || existing.confidence < 1.0)
1579
+ returnTypeMap.set(fnName, { type: typeName, confidence: 1.0 });
1580
+ return;
1581
+ }
1582
+ }
1583
+ // Infer from first `return new Constructor()` in the function body
1584
+ const body = fnNode.childForFieldName('body');
1585
+ if (body) {
1586
+ const inferred = findReturnNewExprType(body);
1587
+ if (inferred) {
1588
+ const existing = returnTypeMap.get(fnName);
1589
+ if (!existing || INFERRED_RETURN_TYPE_CONFIDENCE > existing.confidence)
1590
+ returnTypeMap.set(fnName, { type: inferred, confidence: INFERRED_RETURN_TYPE_CONFIDENCE });
1591
+ }
1592
+ }
1593
+ }
1594
+ /** Return the constructor name from the first `return new Constructor()` in a body, or null. */
1595
+ function findReturnNewExprType(bodyNode) {
1596
+ for (let i = 0; i < bodyNode.childCount; i++) {
1597
+ const child = bodyNode.child(i);
1598
+ if (child?.type !== 'return_statement')
1599
+ continue;
1600
+ for (let j = 0; j < child.childCount; j++) {
1601
+ const expr = child.child(j);
1602
+ if (expr?.type === 'new_expression')
1603
+ return extractNewExprTypeName(expr);
1604
+ }
1605
+ }
1606
+ return null;
1607
+ }
1608
+ /**
1609
+ * Resolve the return type of a call_expression node using returnTypeMap.
1610
+ * Handles: createUser() (identifier), service.getRepo() (member), and
1611
+ * getService().getRepo() (chained call) up to MAX_PROPAGATION_DEPTH hops.
1612
+ *
1613
+ * `depth` tracks total chain hops consumed so far. Each call boundary — both
1614
+ * resolving the receiver and resolving the final return type — costs one hop.
1615
+ * Confidence = annotated return type confidence − 0.1 × (depth + 1).
1616
+ *
1617
+ * Examples (annotated sources → confidence 1.0):
1618
+ * createUser() depth=0 → 1.0 − 0.1 = 0.9 (1 hop)
1619
+ * svc.getUser() depth=0 → 1.0 − 0.1 = 0.9 (1 hop; receiver from typeMap)
1620
+ * getService().getRepo() depth=0 → inner resolved at depth=1, outer at depth+1 → 0.8 (2 hops)
1621
+ */
1622
+ function resolveCallExprReturnType(callNode, typeMap, returnTypeMap, depth) {
1623
+ if (depth >= MAX_PROPAGATION_DEPTH)
1624
+ return null;
1625
+ const fn = callNode.childForFieldName('function');
1626
+ if (!fn)
1627
+ return null;
1628
+ if (fn.type === 'identifier') {
1629
+ const entry = returnTypeMap.get(fn.text);
1630
+ if (!entry)
1631
+ return null;
1632
+ const confidence = entry.confidence - PROPAGATION_HOP_PENALTY * (depth + 1);
1633
+ return confidence > 0 ? { type: entry.type, confidence } : null;
1634
+ }
1635
+ if (fn.type === 'member_expression') {
1636
+ const obj = fn.childForFieldName('object');
1637
+ const prop = fn.childForFieldName('property');
1638
+ if (!obj || !prop)
1639
+ return null;
1640
+ let receiverType = null;
1641
+ // effectiveDepth tracks the depth at which THIS call's return type is charged.
1642
+ // When the receiver is itself a call expression (chain), we've already consumed
1643
+ // a hop resolving it, so charge this call at depth+1.
1644
+ let effectiveDepth = depth;
1645
+ if (obj.type === 'identifier') {
1646
+ const typeEntry = typeMap.get(obj.text);
1647
+ receiverType = typeEntry ? typeEntry.type : null;
1648
+ }
1649
+ else if (obj.type === 'call_expression') {
1650
+ // Each link in a call chain costs an extra hop.
1651
+ const innerResult = resolveCallExprReturnType(obj, typeMap, returnTypeMap, depth + 1);
1652
+ receiverType = innerResult ? innerResult.type : null;
1653
+ effectiveDepth = depth + 1;
1654
+ }
1655
+ if (receiverType) {
1656
+ const entry = returnTypeMap.get(`${receiverType}.${prop.text}`);
1657
+ if (entry) {
1658
+ const confidence = entry.confidence - PROPAGATION_HOP_PENALTY * (effectiveDepth + 1);
1659
+ return confidence > 0 ? { type: entry.type, confidence } : null;
1660
+ }
1661
+ }
1662
+ }
1663
+ return null;
1664
+ }
1665
+ /**
1666
+ * Record a call assignment into callAssignments for cross-file propagation.
1667
+ * Only records cases where the callee is a simple identifier or a method call
1668
+ * on a known-typed variable — chain expressions are skipped (handled locally).
1669
+ */
1670
+ function recordCallAssignment(callNode, varName, typeMap, callAssignments) {
1671
+ const fn = callNode.childForFieldName('function');
1672
+ if (!fn)
1673
+ return;
1674
+ if (fn.type === 'identifier') {
1675
+ callAssignments.push({ varName, calleeName: fn.text });
1676
+ }
1677
+ else if (fn.type === 'member_expression') {
1678
+ const obj = fn.childForFieldName('object');
1679
+ const prop = fn.childForFieldName('property');
1680
+ if (obj?.type === 'identifier' && prop) {
1681
+ const receiverEntry = typeMap.get(obj.text);
1682
+ callAssignments.push({
1683
+ varName,
1684
+ calleeName: prop.text,
1685
+ receiverTypeName: receiverEntry?.type,
1686
+ });
1687
+ }
1688
+ }
1689
+ }
1690
+ /**
1691
+ * Phase 8.5 (RTA): collect all constructor names from `new X()` expressions
1692
+ * in the file. Captures both assigned (`const x = new Foo()`) and unassigned
1693
+ * (`doSomething(new Foo())`) usages that the typeMap-based approach would miss.
1694
+ */
1695
+ // `new X()` constructor-name collection (Phase 8.5 RTA instantiation tracking)
1696
+ // happens inline in runCollectorWalk's new_expression case.
1697
+ /**
1698
+ * Walk the AST to find `Object.defineProperty(obj, "bar", { get: getter })` patterns
1699
+ * and record which functions are used as getter/setter accessors for which objects.
1700
+ *
1701
+ * Result is stored in the provided map as `funcName → receiverVarName`.
1702
+ */
1703
+ function collectDefinePropertyReceiver(node, out) {
1704
+ const fn = node.childForFieldName('function');
1705
+ // Match `Object.defineProperty`
1706
+ if (fn?.type !== 'member_expression')
1707
+ return;
1708
+ const obj = fn.childForFieldName('object');
1709
+ const prop = fn.childForFieldName('property');
1710
+ if (obj?.type !== 'identifier' || obj.text !== 'Object' || prop?.text !== 'defineProperty') {
1711
+ return;
1712
+ }
1713
+ const argsNode = node.childForFieldName('arguments') ?? findChild(node, 'arguments');
1714
+ if (!argsNode)
1715
+ return;
1716
+ // Collect non-punctuation children: arg0 (target obj), arg1 (prop name string), arg2 (descriptor)
1717
+ const argChildren = [];
1718
+ for (let i = 0; i < argsNode.childCount; i++) {
1719
+ const c = argsNode.child(i);
1720
+ if (!c)
1721
+ continue;
1722
+ if (c.type === ',' || c.type === '(' || c.type === ')')
1723
+ continue;
1724
+ argChildren.push(c);
1725
+ }
1726
+ if (argChildren.length < 3)
1727
+ return;
1728
+ const targetObj = argChildren[0];
1729
+ const descriptor = argChildren[2];
1730
+ if (targetObj?.type !== 'identifier' || descriptor?.type !== 'object')
1731
+ return;
1732
+ const targetName = targetObj.text;
1733
+ // Walk the descriptor object's pair children looking for get/set
1734
+ for (let i = 0; i < descriptor.childCount; i++) {
1735
+ const pair = descriptor.child(i);
1736
+ if (pair?.type !== 'pair')
1737
+ continue;
1738
+ const key = pair.childForFieldName('key');
1739
+ const val = pair.childForFieldName('value');
1740
+ if (key &&
1741
+ (key.text === 'get' || key.text === 'set') &&
1742
+ val?.type === 'identifier' &&
1743
+ !BUILTIN_GLOBALS.has(val.text)) {
1744
+ // Known limitation: if the same function is registered as an
1745
+ // accessor on multiple objects, last-write-wins — only the
1746
+ // last target object is retained. This is an unusual pattern
1747
+ // (sharing one function across multiple defineProperty calls)
1748
+ // and covering it would require Map<string, string[]> which
1749
+ // changes the consumer API. Tracked as a known edge case.
1750
+ out.set(val.text, targetName);
1751
+ }
1752
+ }
1753
+ }
1754
+ /**
1755
+ * Single context-tracking pass combining what were three separate full-tree
1756
+ * walks (typeMap, object-rest params, spread/for-of) — see runCollectorWalk
1757
+ * for why traversal count dominates extraction cost on WASM trees.
1758
+ *
1759
+ * Each concern keeps its own enclosing-class register because their reset
1760
+ * rules intentionally differ:
1761
+ *
1762
+ * - typeMap (`typeMapClass`): extracts variable-to-type assignments.
1763
+ * Values are `{ type: string, confidence: number }`:
1764
+ * - 1.0: explicit constructor (`new Foo()`)
1765
+ * - 0.9: type annotation (`: Foo`) or typed parameter
1766
+ * - 0.85: property write (`obj.prop = fn` — Phase 8.3d pts tracking)
1767
+ * - 0.7–0.9: inter-procedural propagation from return-type map (Phase 8.2)
1768
+ * - 0.7: factory method call (`Foo.create()` — uppercase-first heuristic)
1769
+ * Higher-confidence entries take priority when the same variable is seen
1770
+ * twice. Class declarations propagate their name into the subtree; class
1771
+ * *expressions* (`const Foo = class Bar { … }`) propagate null because the
1772
+ * expression-internal name is never visible to the resolver, preserving the
1773
+ * `this.prop` fallback in resolveByMethodOrGlobal. No reset at function
1774
+ * boundaries.
1775
+ *
1776
+ * - object-rest params (`objectRestClass`, Phase 8.3f): context flows only
1777
+ * class_declaration/class → class_body → method_definition so methods are
1778
+ * keyed "ClassName.method"; every other node type resets to null, and
1779
+ * function/method bodies recurse with null so nested declarations don't
1780
+ * inherit the class context.
1781
+ *
1782
+ * - spread/for-of (`funcStack`/`classStack`, Phase 8.3e): tracks the
1783
+ * enclosing *function* (not just class) via push/pop so for-of bindings
1784
+ * record the qualified enclosing callable (e.g. 'Foo.bar', 'obj.method',
1785
+ * or '<module>' at top level).
1786
+ *
1787
+ * NOTE: returnTypeMap population stays a separate, earlier pass
1788
+ * (extractReturnTypeMapWalk) — handleVarDeclaratorTypeMap reads it for
1789
+ * inter-procedural propagation, so it must be complete for the whole file
1790
+ * before any declarator is processed (a function declared *after* its first
1791
+ * use would otherwise be missed).
1792
+ */
1793
+ function runContextCollectorWalk(rootNode, out) {
1794
+ const funcStack = [];
1795
+ const classStack = [];
1796
+ const walk = (node, depth, typeMapClass, objectRestClass) => {
1797
+ if (depth >= MAX_WALK_DEPTH)
1798
+ return;
1799
+ const t = node.type;
1800
+ const isClassDecl = t === 'class_declaration' || t === 'abstract_class_declaration';
1801
+ const isClassExpr = t === 'class';
1802
+ const isFnDecl = t === 'function_declaration' || t === 'generator_function_declaration';
1803
+ // Class name read once, shared by every concern that needs it below.
1804
+ let className = null;
1805
+ let classNameIsIdentifier = false;
1806
+ if (isClassDecl || isClassExpr) {
1807
+ const nameNode = node.childForFieldName('name');
1808
+ className = nameNode?.text ?? null;
1809
+ classNameIsIdentifier = nameNode?.type === 'identifier';
1810
+ }
1811
+ // ── spread/for-of enclosing-context stacks (push on enter, pop after children) ──
1812
+ let pushedFunc = false;
1813
+ let pushedClass = false;
1814
+ if (isClassDecl || isClassExpr) {
1815
+ // The stack push keeps the original walk's `identifier`-only check (TS
1816
+ // class names parse as type_identifier and were never pushed), while
1817
+ // typeMapClass/objectRestClass below use the bare text like their
1818
+ // original walks did.
1819
+ if (className && classNameIsIdentifier) {
1820
+ classStack.push(className);
1821
+ pushedClass = true;
1822
+ }
1823
+ }
1824
+ else if (isFnDecl) {
1825
+ const nameNode = node.childForFieldName('name');
1826
+ if (nameNode?.type === 'identifier') {
1827
+ funcStack.push(nameNode.text);
1828
+ pushedFunc = true;
1829
+ }
1830
+ }
1831
+ else if (t === 'method_definition') {
1832
+ const nameNode = node.childForFieldName('name');
1833
+ if (nameNode) {
1834
+ // Qualify with the enclosing class name so the PTS key matches
1835
+ // callerName from findCaller (which uses def.name = 'ClassName.method').
1836
+ const enclosingClass = classStack.length > 0 ? classStack[classStack.length - 1] : null;
1837
+ let rawName;
1838
+ if (nameNode.type === 'computed_property_name') {
1839
+ const inner = nameNode.child(1);
1840
+ if (!inner || (inner.type !== 'string' && inner.type !== 'string_fragment')) {
1841
+ // Non-string computed key — skip adding to funcStack (no resolvable name).
1842
+ rawName = '';
1843
+ }
1844
+ else {
1845
+ rawName = inner.text.replace(/^['"]|['"]$/g, '');
1846
+ }
1847
+ }
1848
+ else {
1849
+ rawName = nameNode.text;
1850
+ }
1851
+ if (rawName) {
1852
+ const qualifiedName = enclosingClass ? `${enclosingClass}.${rawName}` : rawName;
1853
+ funcStack.push(qualifiedName);
1854
+ pushedFunc = true;
1855
+ }
1856
+ }
1857
+ }
1858
+ else if (t === 'variable_declarator') {
1859
+ // `const process = (arr) => { ... }` — arrow/expression functions assigned
1860
+ // to a variable have no `name` field on the function node itself.
1861
+ const nameNode = node.childForFieldName('name');
1862
+ const valueNode = node.childForFieldName('value');
1863
+ if (nameNode?.type === 'identifier' &&
1864
+ (valueNode?.type === 'arrow_function' || valueNode?.type === 'function_expression')) {
1865
+ funcStack.push(nameNode.text);
1866
+ pushedFunc = true;
1867
+ }
1868
+ }
1869
+ else if (t === 'assignment_expression') {
1870
+ // `obj.method = function() { ... }` — func-prop assignment.
1871
+ // Mirror handleFuncPropAssignment's logic so for-of loops inside the
1872
+ // body get the correct enclosingFunc (e.g. 'obj.method') instead of
1873
+ // '<module>' or the wrong outer function name.
1874
+ const lhs = node.childForFieldName('left');
1875
+ const rhs = node.childForFieldName('right');
1876
+ if (lhs?.type === 'member_expression' &&
1877
+ (rhs?.type === 'function_expression' || rhs?.type === 'arrow_function')) {
1878
+ const obj = lhs.childForFieldName('object');
1879
+ const prop = lhs.childForFieldName('property');
1880
+ if (obj?.type === 'identifier' &&
1881
+ (prop?.type === 'property_identifier' || prop?.type === 'identifier') &&
1882
+ !BUILTIN_GLOBALS.has(obj.text) &&
1883
+ prop.text !== 'prototype') {
1884
+ funcStack.push(`${obj.text}.${prop.text}`);
1885
+ pushedFunc = true;
1886
+ }
1887
+ }
1888
+ }
1889
+ // ── per-node collectors (class nodes match none of these types) ──
1890
+ if (t === 'variable_declarator') {
1891
+ handleVarDeclaratorTypeMap(node, out.typeMap, out.returnTypeMap, out.callAssignments, out.fnRefBindings);
1892
+ collectCollectionWrapBinding(node, out.fnRefBindings);
1893
+ }
1894
+ else if (t === 'required_parameter' || t === 'optional_parameter') {
1895
+ handleParamTypeMap(node, out.typeMap);
1896
+ }
1897
+ else if (t === 'public_field_definition' || t === 'field_definition') {
1898
+ handleFieldDefTypeMap(node, out.typeMap, typeMapClass);
1899
+ }
1900
+ else if (t === 'assignment_expression') {
1901
+ handlePropWriteTypeMap(node, out.typeMap, typeMapClass);
1902
+ }
1903
+ else if (t === 'call_expression') {
1904
+ handleDefinePropertyTypeMap(node, out.typeMap);
1905
+ collectSpreadAndArrayFromBindings(node, out.spreadArgBindings, out.arrayCallbackBindings);
1906
+ }
1907
+ else if (t === 'for_in_statement') {
1908
+ const enclosingFunc = funcStack.length > 0 ? funcStack[funcStack.length - 1] : '<module>';
1909
+ collectForOfBinding(node, enclosingFunc, out.forOfBindings);
1910
+ }
1911
+ collectObjectRestParams(node, t, objectRestClass, out.objectRestParamBindings);
1912
+ // ── child context per concern ──
1913
+ const childTypeMapClass = isClassDecl ? className : isClassExpr ? null : typeMapClass;
1914
+ let childObjectRestClass = null;
1915
+ if (t === 'class_declaration' || t === 'class') {
1916
+ childObjectRestClass = className;
1917
+ }
1918
+ else if (t === 'class_body') {
1919
+ childObjectRestClass = objectRestClass;
1920
+ }
1921
+ for (let i = 0; i < node.childCount; i++) {
1922
+ walk(node.child(i), depth + 1, childTypeMapClass, childObjectRestClass);
1923
+ }
1924
+ if (pushedFunc)
1925
+ funcStack.pop();
1926
+ if (pushedClass)
1927
+ classStack.pop();
1928
+ };
1929
+ walk(rootNode, 0, null, null);
1930
+ }
1931
+ /**
1932
+ * Record function-reference bindings from a variable_declarator's value node.
1933
+ *
1934
+ * Captures three patterns (Phase 8.3):
1935
+ * - `const fn = handler` (identifier alias)
1936
+ * - `const fn = obj.method` (member_expression alias)
1937
+ * - `const f = fn.bind(ctx)` (bind creates a bound alias)
1938
+ *
1939
+ * Must be called before any type-analysis early returns so every declarator
1940
+ * contributes to fnRefBindings regardless of whether it has a type annotation.
1941
+ */
1942
+ function collectFnRefBindings(lhsName, valueN, fnRefBindings) {
1943
+ if (valueN.type === 'identifier' && !BUILTIN_GLOBALS.has(valueN.text)) {
1944
+ fnRefBindings.push({ lhs: lhsName, rhs: valueN.text });
1945
+ return;
1946
+ }
1947
+ if (valueN.type === 'member_expression') {
1948
+ const prop = valueN.childForFieldName('property');
1949
+ const obj = valueN.childForFieldName('object');
1950
+ // Guard: only static property access (property_identifier or identifier), not
1951
+ // computed subscript expressions like obj[expr] where prop.text would be the
1952
+ // full expression rather than a simple name — those can never match pts keys.
1953
+ if (prop &&
1954
+ (prop.type === 'property_identifier' || prop.type === 'identifier') &&
1955
+ obj?.type === 'identifier' &&
1956
+ !BUILTIN_GLOBALS.has(obj.text)) {
1957
+ fnRefBindings.push({ lhs: lhsName, rhs: prop.text, rhsReceiver: obj.text });
1958
+ }
1959
+ return;
1960
+ }
1961
+ if (valueN.type === 'call_expression') {
1962
+ // `const f = fn.bind(ctx)` — bind returns a bound copy of fn; track f → fn so
1963
+ // pts(f) ⊇ pts(fn) and subsequent `f(args)` calls resolve to fn.
1964
+ // Note: only flat-identifier binds (fn.bind) are tracked here; method-receiver
1965
+ // binds like `obj.method.bind(ctx)` are not captured (boundFn must be an identifier).
1966
+ const callFn = valueN.childForFieldName('function');
1967
+ if (callFn?.type === 'member_expression') {
1968
+ const bindProp = callFn.childForFieldName('property');
1969
+ if (bindProp?.text === 'bind') {
1970
+ const boundFn = callFn.childForFieldName('object');
1971
+ if (boundFn?.type === 'identifier' && !BUILTIN_GLOBALS.has(boundFn.text)) {
1972
+ fnRefBindings.push({ lhs: lhsName, rhs: boundFn.text });
1973
+ }
1974
+ }
1975
+ }
1976
+ }
1977
+ }
1978
+ /**
1979
+ * Handle the `call_expression` branch of variable_declarator type-map seeding.
1980
+ *
1981
+ * Processes three sub-cases in priority order:
1982
+ * 1. Object.create({ ... }) — seeds composite pts keys from the prototype object (Phase 8.3e)
1983
+ * 2. Inter-procedural return-type propagation via returnTypeMap (Phase 8.2)
1984
+ * 3. Factory method heuristic: `const x = Foo.create()` → type Foo at confidence 0.7
1985
+ */
1986
+ function handleCallExprTypeMap(lhsName, valueN, typeMap, returnTypeMap, callAssignments) {
1987
+ const createFn = valueN.childForFieldName('function');
1988
+ // Phase 8.3e: Object.create({ f1, f2 }) — seed composite pts keys obj.f1 → f1, etc.
1989
+ if (createFn?.type === 'member_expression') {
1990
+ const createObj = createFn.childForFieldName('object');
1991
+ const createProp = createFn.childForFieldName('property');
1992
+ if (createObj?.text === 'Object' && createProp?.text === 'create') {
1993
+ const createArgs = valueN.childForFieldName('arguments') || findChild(valueN, 'arguments');
1994
+ if (createArgs) {
1995
+ let proto = null;
1996
+ for (let i = 0; i < createArgs.childCount; i++) {
1997
+ const n = createArgs.child(i);
1998
+ if (n && n.type !== '(' && n.type !== ')' && n.type !== ',') {
1999
+ proto = n;
2000
+ break;
2001
+ }
2002
+ }
2003
+ if (proto?.type === 'object') {
2004
+ seedProtoProperties(lhsName, proto, typeMap);
2005
+ }
2006
+ }
2007
+ return;
2008
+ }
2009
+ }
2010
+ // Phase 8.2: inter-procedural propagation — try to resolve return type from
2011
+ // the local returnTypeMap before falling back to factory heuristics.
2012
+ if (returnTypeMap) {
2013
+ const result = resolveCallExprReturnType(valueN, typeMap, returnTypeMap, 0);
2014
+ if (result) {
2015
+ setTypeMapEntry(typeMap, lhsName, result.type, result.confidence);
2016
+ return;
2017
+ }
2018
+ }
2019
+ // Record for cross-file resolution in build-edges.ts (imported functions)
2020
+ if (callAssignments) {
2021
+ recordCallAssignment(valueN, lhsName, typeMap, callAssignments);
2022
+ }
2023
+ // Factory method heuristic: const x = Foo.create() → type Foo, confidence 0.7
2024
+ if (createFn?.type === 'member_expression') {
2025
+ const obj = createFn.childForFieldName('object');
2026
+ if (obj?.type === 'identifier') {
2027
+ const objName = obj.text;
2028
+ if (objName[0] && objName[0] !== objName[0].toLowerCase() && !BUILTIN_GLOBALS.has(objName)) {
2029
+ setTypeMapEntry(typeMap, lhsName, objName, 0.7);
2030
+ }
2031
+ }
2032
+ }
2033
+ }
2034
+ /**
2035
+ * Seed composite pts keys from a module-level object literal assignment (Phase 8.3f).
2036
+ *
2037
+ * `const obj = { baz: () => {} }` → typeMap['obj.baz'] = 'obj.baz'
2038
+ * `const obj = { baz }` (shorthand) → typeMap['obj.baz'] = 'baz' (bare identifier target)
2039
+ * `const obj = { baz: otherFn }` → typeMap['obj.baz'] = 'otherFn' (identifier alias)
2040
+ * `const obj = { baz() {} }` (method shorthand) → typeMap['obj.baz'] = 'obj.baz'
2041
+ *
2042
+ * For function/arrow values, the value is the qualified name ('obj.baz') because
2043
+ * extractObjectLiteralFunctions registers definitions under that qualified name to avoid
2044
+ * polluting the global index with bare property names like 'init', 'run', or 'render'.
2045
+ * Enables accessor this-dispatch: when typeMap['getter:this'] = 'obj',
2046
+ * resolving this.baz() inside getter → typeMap['obj.baz'] → 'obj.baz' → lookup.byName('obj.baz').
2047
+ *
2048
+ * Scope guard: caller must ensure `node` is not inside a function body
2049
+ * (mirrors Rust handle_var_decl's find_parent_of_types check — function-scoped
2050
+ * `const localObj = { fn: ... }` must not shadow a module-level `const obj`).
2051
+ */
2052
+ function handleObjectLiteralTypeMap(lhsName, valueN, typeMap) {
2053
+ for (let i = 0; i < valueN.childCount; i++) {
2054
+ const child = valueN.child(i);
2055
+ if (!child)
2056
+ continue;
2057
+ if (child.type === 'shorthand_property_identifier') {
2058
+ setTypeMapEntry(typeMap, `${lhsName}.${child.text}`, child.text, 0.85);
2059
+ }
2060
+ else if (child.type === 'pair') {
2061
+ const keyNode = child.childForFieldName('key');
2062
+ const valNode = child.childForFieldName('value');
2063
+ if (!keyNode || !valNode)
2064
+ continue;
2065
+ const keyName = keyNode.type === 'string' ? keyNode.text.replace(/^['"]|['"]$/g, '') : keyNode.text;
2066
+ if (!keyName)
2067
+ continue;
2068
+ const qualifiedKey = `${lhsName}.${keyName}`;
2069
+ if (valNode.type === 'arrow_function' ||
2070
+ valNode.type === 'function_expression' ||
2071
+ valNode.type === 'function') {
2072
+ // Store the qualified name so the resolver finds the qualified definition.
2073
+ setTypeMapEntry(typeMap, qualifiedKey, qualifiedKey, 0.85);
2074
+ }
2075
+ else if (valNode.type === 'identifier') {
2076
+ setTypeMapEntry(typeMap, qualifiedKey, valNode.text, 0.85);
2077
+ }
2078
+ }
2079
+ else if (child.type === 'method_definition') {
2080
+ // Method shorthand: `const obj = { baz() {} }` → typeMap['obj.baz'] = 'obj.baz'
2081
+ // extractObjectLiteralFunctions registers a definition under the qualified name;
2082
+ // seed the matching typeMap entry so the two-step accessor dispatch finds it.
2083
+ const nameNode = child.childForFieldName('name');
2084
+ if (!nameNode)
2085
+ continue;
2086
+ setTypeMapEntry(typeMap, `${lhsName}.${nameNode.text}`, `${lhsName}.${nameNode.text}`, 0.85);
2087
+ }
2088
+ }
2089
+ }
2090
+ /**
2091
+ * Extract type info from a variable_declarator: type annotation, constructor, or factory.
2092
+ *
2093
+ * Orchestrates four concerns in priority order:
2094
+ * 1. fnRefBindings — always collected first (before any early return)
2095
+ * 2. new_expression — constructor wins over annotation (runtime type is authoritative)
2096
+ * 3. type_annotation — confidence 0.9 for static analysis
2097
+ * 4. call_expression / object literal — delegated to handleCallExprTypeMap /
2098
+ * handleObjectLiteralTypeMap
2099
+ */
2100
+ function handleVarDeclaratorTypeMap(node, typeMap, returnTypeMap, callAssignments, fnRefBindings) {
2101
+ const nameN = node.childForFieldName('name');
2102
+ if (nameN?.type !== 'identifier')
2103
+ return;
2104
+ const typeAnno = findChild(node, 'type_annotation');
2105
+ const valueN = node.childForFieldName('value');
2106
+ // 1. fnRefBindings — must run before any early return so every declarator contributes.
2107
+ if (fnRefBindings && valueN) {
2108
+ collectFnRefBindings(nameN.text, valueN, fnRefBindings);
2109
+ }
2110
+ // 2. Constructor wins over annotation: `const x: Base = new Derived()` resolves to Derived.
2111
+ if (valueN?.type === 'new_expression') {
2112
+ const ctorType = extractNewExprTypeName(valueN);
2113
+ if (ctorType) {
2114
+ setTypeMapEntry(typeMap, nameN.text, ctorType, 1.0);
2115
+ return;
2116
+ }
2117
+ }
2118
+ // 3. Type annotation — confidence 0.9.
2119
+ if (typeAnno) {
2120
+ const typeName = extractSimpleTypeName(typeAnno);
2121
+ if (typeName) {
2122
+ setTypeMapEntry(typeMap, nameN.text, typeName, 0.9);
2123
+ return;
2124
+ }
2125
+ }
2126
+ if (!valueN)
2127
+ return;
2128
+ if (valueN.type === 'new_expression')
2129
+ return;
2130
+ // 4a. call_expression — Object.create / return-type propagation / factory heuristic.
2131
+ if (valueN.type === 'call_expression') {
2132
+ handleCallExprTypeMap(nameN.text, valueN, typeMap, returnTypeMap, callAssignments);
2133
+ return;
2134
+ }
2135
+ // 4b. Object literal — seed composite pts keys for module-level const objects.
2136
+ if (valueN.type === 'object' && !hasFunctionScopeAncestor(node)) {
2137
+ handleObjectLiteralTypeMap(nameN.text, valueN, typeMap);
2138
+ }
2139
+ }
2140
+ /** Extract type info from a required_parameter or optional_parameter. */
2141
+ function handleParamTypeMap(node, typeMap) {
2142
+ const nameNode = node.childForFieldName('pattern') || node.childForFieldName('left') || node.child(0);
2143
+ if (nameNode?.type !== 'identifier')
2144
+ return;
2145
+ const typeAnno = findChild(node, 'type_annotation');
2146
+ if (typeAnno) {
2147
+ const typeName = extractSimpleTypeName(typeAnno);
2148
+ if (typeName)
2149
+ setTypeMapEntry(typeMap, nameNode.text, typeName, 0.9);
2150
+ }
2151
+ }
2152
+ /**
2153
+ * Extract type info from a class field declaration: `private repo: Repository<User>`.
2154
+ *
2155
+ * Seeds a class-scoped key `ClassName.field` (confidence 0.9) as the primary entry
2156
+ * so that two classes with identically-named fields don't overwrite each other's
2157
+ * typeMap entry (issue #1458). The resolver's `CallerClass.X` fallback (call-resolver.ts
2158
+ * line 110) looks up exactly this key.
2159
+ *
2160
+ * Bare `field` and `this.field` keys are kept at lower confidence (0.6) as fallbacks
2161
+ * for single-class files where the resolver may not have a callerClass context.
2162
+ *
2163
+ * Mirrors the field_definition branch of match_js_type_map in
2164
+ * crates/codegraph-core/src/extractors/javascript.rs.
2165
+ */
2166
+ function handleFieldDefTypeMap(node, typeMap, currentClass) {
2167
+ const nameNode = node.childForFieldName('name') ||
2168
+ node.childForFieldName('property') ||
2169
+ findChild(node, 'property_identifier');
2170
+ if (!nameNode)
2171
+ return;
2172
+ const kind = nameNode.type;
2173
+ if (kind !== 'property_identifier' &&
2174
+ kind !== 'identifier' &&
2175
+ kind !== 'private_property_identifier')
2176
+ return;
2177
+ const typeAnno = findChild(node, 'type_annotation');
2178
+ if (!typeAnno)
2179
+ return;
2180
+ const typeName = extractSimpleTypeName(typeAnno);
2181
+ if (!typeName)
2182
+ return;
2183
+ if (currentClass) {
2184
+ // Primary: class-scoped key prevents cross-class collision (issue #1458).
2185
+ setTypeMapEntry(typeMap, `${currentClass}.${nameNode.text}`, typeName, 0.9);
2186
+ // Fallback: bare keys at lower confidence for single-class files or when
2187
+ // the resolver does not have a callerClass in scope.
2188
+ setTypeMapEntry(typeMap, nameNode.text, typeName, 0.6);
2189
+ setTypeMapEntry(typeMap, `this.${nameNode.text}`, typeName, 0.6);
2190
+ }
2191
+ else {
2192
+ // No enclosing class declaration (e.g. class expression) — use bare keys only.
2193
+ setTypeMapEntry(typeMap, nameNode.text, typeName, 0.9);
2194
+ setTypeMapEntry(typeMap, `this.${nameNode.text}`, typeName, 0.9);
2195
+ }
2196
+ }
2197
+ /**
2198
+ * Phase 8.3d: seed the pts map from object property writes.
2199
+ *
2200
+ * `handlers.auth = authMiddleware` → typeMap.set('handlers.auth', { type: 'authMiddleware', confidence: 0.85 })
2201
+ * `this.logger = new Logger(...)` → typeMap.set('UserService.logger', { type: 'Logger', confidence: 1.0 })
2202
+ * (keyed as ClassName.prop when currentClass is known, to avoid collisions across classes)
2203
+ *
2204
+ * Only simple `obj.prop = identifier` and `this.prop = new Ctor()` writes are tracked
2205
+ * (not chained `a.b.c = x`). BUILTIN_GLOBALS are skipped (e.g. `console.log = fn`).
2206
+ */
2207
+ function handlePropWriteTypeMap(node, typeMap, currentClass) {
2208
+ const lhsN = node.childForFieldName('left');
2209
+ const rhsN = node.childForFieldName('right');
2210
+ if (!lhsN || !rhsN)
2211
+ return;
2212
+ if (lhsN.type !== 'member_expression')
2213
+ return;
2214
+ const obj = lhsN.childForFieldName('object');
2215
+ const prop = lhsN.childForFieldName('property');
2216
+ if (!obj || !prop)
2217
+ return;
2218
+ // Guard: only static property access (property_identifier or identifier), not
2219
+ // computed subscript expressions — consistent with the adjacent fnRefBindings block.
2220
+ if (prop.type !== 'property_identifier' && prop.type !== 'identifier')
2221
+ return;
2222
+ // this.prop = new ClassName(...) — constructor-assigned property type.
2223
+ // Key as ClassName.prop (class-scoped) so two classes with identically-named
2224
+ // properties don't overwrite each other's typeMap entry.
2225
+ if (obj.type === 'this' && rhsN.type === 'new_expression') {
2226
+ const ctorType = extractNewExprTypeName(rhsN);
2227
+ if (ctorType) {
2228
+ const key = currentClass ? `${currentClass}.${prop.text}` : `this.${prop.text}`;
2229
+ setTypeMapEntry(typeMap, key, ctorType, 1.0);
2230
+ }
2231
+ return;
2232
+ }
2233
+ // obj.prop = identifier — existing behaviour (skip chained a.b.c = x and builtins)
2234
+ if (rhsN.type !== 'identifier')
2235
+ return;
2236
+ if (obj.type !== 'identifier')
2237
+ return;
2238
+ const objName = obj.text;
2239
+ if (BUILTIN_GLOBALS.has(objName))
2240
+ return;
2241
+ setTypeMapEntry(typeMap, `${objName}.${prop.text}`, rhsN.text, 0.85);
2242
+ }
2243
+ /**
2244
+ * Phase 8.3e/8.3f: seed composite pts keys from Object.defineProperty / defineProperties.
2245
+ *
2246
+ * `Object.defineProperty(obj, "key", { value: fn })` → typeMap.set('obj.key', fn, 0.85)
2247
+ * `Object.defineProperties(obj, { "k1": { value: v1 } })` → typeMap.set('obj.k1', v1, 0.85)
2248
+ * `Object.defineProperty(obj, "key", { get: getter })` → typeMap.set('getter:this', obj, 0.85)
2249
+ */
2250
+ function handleDefinePropertyTypeMap(node, typeMap) {
2251
+ const fn = node.childForFieldName('function');
2252
+ if (fn?.type !== 'member_expression')
2253
+ return;
2254
+ const fnObj = fn.childForFieldName('object');
2255
+ const fnProp = fn.childForFieldName('property');
2256
+ if (fnObj?.text !== 'Object')
2257
+ return;
2258
+ const method = fnProp?.text;
2259
+ if (method !== 'defineProperty' && method !== 'defineProperties')
2260
+ return;
2261
+ const argsNode = node.childForFieldName('arguments') || findChild(node, 'arguments');
2262
+ if (!argsNode)
2263
+ return;
2264
+ const args = [];
2265
+ for (let i = 0; i < argsNode.childCount; i++) {
2266
+ const n = argsNode.child(i);
2267
+ if (n && n.type !== '(' && n.type !== ')' && n.type !== ',')
2268
+ args.push(n);
2269
+ }
2270
+ if (method === 'defineProperty') {
2271
+ if (args.length < 3)
2272
+ return;
2273
+ const arg0 = args[0], arg1 = args[1], arg2 = args[2];
2274
+ if (arg0.type !== 'identifier')
2275
+ return;
2276
+ if (arg1.type !== 'string')
2277
+ return;
2278
+ const key = arg1.text.replace(/^['"]|['"]$/g, '');
2279
+ if (!key)
2280
+ return;
2281
+ // Phase 8.3e: { value: fn } → obj.key pts to fn
2282
+ const target = findDescriptorValue(arg2);
2283
+ if (target) {
2284
+ setTypeMapEntry(typeMap, `${arg0.text}.${key}`, target, 0.85);
2285
+ }
2286
+ // Phase 8.3f: { get: getter } and/or { set: setter } → this inside each accessor is arg0 (obj)
2287
+ // Key format: '<accessorName>:this' — colon is a reserved separator used only by this phase.
2288
+ // JS identifiers cannot contain ':', so this key never collides with real variable names.
2289
+ for (const accessor of findDescriptorAccessors(arg2)) {
2290
+ setTypeMapEntry(typeMap, `${accessor}:this`, arg0.text, 0.85);
2291
+ }
2292
+ }
2293
+ else {
2294
+ // defineProperties
2295
+ if (args.length < 2)
2296
+ return;
2297
+ const arg0 = args[0], arg1 = args[1];
2298
+ if (arg0.type !== 'identifier')
2299
+ return;
2300
+ if (arg1.type !== 'object')
2301
+ return;
2302
+ for (let i = 0; i < arg1.childCount; i++) {
2303
+ const pair = arg1.child(i);
2304
+ if (pair?.type !== 'pair')
2305
+ continue;
2306
+ const keyN = pair.childForFieldName('key');
2307
+ const valN = pair.childForFieldName('value');
2308
+ if (!keyN || !valN)
2309
+ continue;
2310
+ const key = keyN.type === 'string' ? keyN.text.replace(/^['"]|['"]$/g, '') : keyN.text;
2311
+ const target = findDescriptorValue(valN);
2312
+ if (!target)
2313
+ continue;
2314
+ setTypeMapEntry(typeMap, `${arg0.text}.${key}`, target, 0.85);
2315
+ }
2316
+ }
2317
+ }
2318
+ /** Return the identifier text of the `value` field in a property descriptor object. */
2319
+ function findDescriptorValue(desc) {
2320
+ if (desc.type !== 'object')
2321
+ return undefined;
2322
+ for (let i = 0; i < desc.childCount; i++) {
2323
+ const pair = desc.child(i);
2324
+ if (pair?.type !== 'pair')
2325
+ continue;
2326
+ const key = pair.childForFieldName('key');
2327
+ const val = pair.childForFieldName('value');
2328
+ if (key?.text === 'value' && val?.type === 'identifier')
2329
+ return val.text;
2330
+ }
2331
+ return undefined;
2332
+ }
2333
+ /**
2334
+ * Phase 8.3f: return the identifier texts of all `get` and `set` accessors in a property
2335
+ * descriptor. `{ get: getter, set: setter }` → ['getter', 'setter'].
2336
+ * Returns all accessors so that each one gets a `callerName:this = obj` typeMap entry.
2337
+ */
2338
+ function findDescriptorAccessors(desc) {
2339
+ if (desc.type !== 'object')
2340
+ return [];
2341
+ const result = [];
2342
+ for (let i = 0; i < desc.childCount; i++) {
2343
+ const pair = desc.child(i);
2344
+ if (pair?.type !== 'pair')
2345
+ continue;
2346
+ const key = pair.childForFieldName('key');
2347
+ const val = pair.childForFieldName('value');
2348
+ if ((key?.text === 'get' || key?.text === 'set') && val?.type === 'identifier') {
2349
+ result.push(val.text);
2350
+ }
2351
+ }
2352
+ return result;
2353
+ }
2354
+ /** Seed composite pts keys for each property in a prototype object literal. */
2355
+ function seedProtoProperties(varName, proto, typeMap) {
2356
+ for (let i = 0; i < proto.childCount; i++) {
2357
+ const child = proto.child(i);
2358
+ if (!child)
2359
+ continue;
2360
+ if (child.type === 'shorthand_property_identifier') {
2361
+ setTypeMapEntry(typeMap, `${varName}.${child.text}`, child.text, 0.85);
2362
+ }
2363
+ else if (child.type === 'pair') {
2364
+ const keyN = child.childForFieldName('key');
2365
+ const valN = child.childForFieldName('value');
2366
+ if (!keyN || !valN || valN.type !== 'identifier')
2367
+ continue;
2368
+ const key = keyN.type === 'string' ? keyN.text.replace(/^['"]|['"]$/g, '') : keyN.text;
2369
+ setTypeMapEntry(typeMap, `${varName}.${key}`, valN.text, 0.85);
2370
+ }
2371
+ }
2372
+ }
2373
+ /**
2374
+ * Phase 8.3c: record argument-to-parameter bindings at call sites.
2375
+ *
2376
+ * For each `f(x, y)` where the callee is a simple identifier and an argument
2377
+ * is a simple identifier, emits a ParamBinding so the pts solver can add
2378
+ * constraint: pts(param_i_of_f) ⊇ pts(arg_i). The solver uses the
2379
+ * definitionParams map to resolve the actual parameter names.
2380
+ *
2381
+ * Scope: intra-module only (the solver only materialises constraints for
2382
+ * locally-defined callees, so cross-module calls produce no spurious flow).
2383
+ */
2384
+ function collectParamBindings(node, paramBindings) {
2385
+ const fn = node.childForFieldName('function');
2386
+ const args = node.childForFieldName('arguments') ?? findChild(node, 'arguments');
2387
+ if (fn?.type === 'identifier' && !BUILTIN_GLOBALS.has(fn.text) && args) {
2388
+ let argIdx = 0;
2389
+ for (let i = 0; i < args.childCount; i++) {
2390
+ const child = args.child(i);
2391
+ if (!child)
2392
+ continue;
2393
+ const ct = child.type;
2394
+ if (ct === ',' || ct === '(' || ct === ')')
2395
+ continue;
2396
+ if (ct === 'identifier' && !BUILTIN_GLOBALS.has(child.text)) {
2397
+ paramBindings.push({ callee: fn.text, argIndex: argIdx, argName: child.text });
2398
+ }
2399
+ else if (ct === 'spread_element') {
2400
+ // f(...[a, b]) — inline array literal: expand each element as a direct param binding.
2401
+ const inner = child.childForFieldName('argument') ?? (child.childCount > 1 ? child.child(1) : null);
2402
+ if (inner?.type === 'array') {
2403
+ let elemCount = 0;
2404
+ for (let j = 0; j < inner.childCount; j++) {
2405
+ const elem = inner.child(j);
2406
+ if (!elem)
2407
+ continue;
2408
+ if (elem.type === ',' || elem.type === '[' || elem.type === ']')
2409
+ continue;
2410
+ if (elem.type === 'identifier' && !BUILTIN_GLOBALS.has(elem.text)) {
2411
+ paramBindings.push({
2412
+ callee: fn.text,
2413
+ argIndex: argIdx + elemCount,
2414
+ argName: elem.text,
2415
+ });
2416
+ }
2417
+ elemCount++;
2418
+ }
2419
+ // Advance by the exact number of slots this spread occupies and skip
2420
+ // the unconditional argIdx++ below so that zero-element spreads (...[])
2421
+ // do not shift subsequent argument indices.
2422
+ argIdx += elemCount;
2423
+ continue;
2424
+ }
2425
+ }
2426
+ argIdx++;
2427
+ }
2428
+ }
2429
+ }
2430
+ /** Collection constructors whose argument is treated as an element source. */
2431
+ const COLLECTION_CTOR_SET = new Set(['Set', 'Map']);
2432
+ /**
2433
+ * Phase 8.3e: Extract array-element bindings from `const arr = [fn1, fn2]` patterns.
2434
+ * Emits an ArrayElemBinding for each identifier element in an array literal assigned
2435
+ * to a variable.
2436
+ */
2437
+ function collectArrayElemBindings(node, arrayElemBindings) {
2438
+ const nameN = node.childForFieldName('name');
2439
+ const valueN = node.childForFieldName('value');
2440
+ if (nameN?.type === 'identifier' && valueN?.type === 'array') {
2441
+ let idx = 0;
2442
+ for (let i = 0; i < valueN.childCount; i++) {
2443
+ const elem = valueN.child(i);
2444
+ if (!elem)
2445
+ continue;
2446
+ if (elem.type === ',' || elem.type === '[' || elem.type === ']')
2447
+ continue;
2448
+ if (elem.type === 'identifier' && !BUILTIN_GLOBALS.has(elem.text)) {
2449
+ arrayElemBindings.push({ arrayName: nameN.text, index: idx, elemName: elem.text });
2450
+ }
2451
+ idx++;
2452
+ }
2453
+ }
2454
+ }
2455
+ /**
2456
+ * Phase 8.3e collectors (spread-argument, Array.from, collection-wrap, for-of
2457
+ * bindings), invoked from runContextCollectorWalk:
2458
+ *
2459
+ * - Spread: `f(...arr)` → SpreadArgBinding
2460
+ * - Array.from: `Array.from(src, cb)` → ArrayCallbackBinding
2461
+ * - Collection wrap: `new Set(arr)` / `new Map(arr)` → FnRefBinding lhs=s[*] rhs=arr[*]
2462
+ * - For-of: `for (const x of arr)` → ForOfBinding
2463
+ */
2464
+ function collectSpreadAndArrayFromBindings(node, spreadArgBindings, arrayCallbackBindings) {
2465
+ const fn = node.childForFieldName('function');
2466
+ const argsNode = node.childForFieldName('arguments') ?? findChild(node, 'arguments');
2467
+ // Spread: f(...arr)
2468
+ if (fn?.type === 'identifier' && !BUILTIN_GLOBALS.has(fn.text) && argsNode) {
2469
+ let argIdx = 0;
2470
+ for (let i = 0; i < argsNode.childCount; i++) {
2471
+ const child = argsNode.child(i);
2472
+ if (!child)
2473
+ continue;
2474
+ if (child.type === ',' || child.type === '(' || child.type === ')')
2475
+ continue;
2476
+ if (child.type === 'spread_element') {
2477
+ const spreadTarget = child.childForFieldName('argument') ?? (child.childCount > 1 ? child.child(1) : null);
2478
+ if (spreadTarget?.type === 'identifier' && !BUILTIN_GLOBALS.has(spreadTarget.text)) {
2479
+ spreadArgBindings.push({
2480
+ callee: fn.text,
2481
+ arrayName: spreadTarget.text,
2482
+ startIndex: argIdx,
2483
+ });
2484
+ }
2485
+ }
2486
+ argIdx++;
2487
+ }
2488
+ }
2489
+ // Array.from(source, cb)
2490
+ if (fn?.type === 'member_expression' && argsNode) {
2491
+ const obj = fn.childForFieldName('object');
2492
+ const prop = fn.childForFieldName('property');
2493
+ if (obj?.text === 'Array' && prop?.text === 'from') {
2494
+ const fnArgs = [];
2495
+ for (let i = 0; i < argsNode.childCount; i++) {
2496
+ const child = argsNode.child(i);
2497
+ if (!child)
2498
+ continue;
2499
+ if (child.type === ',' || child.type === '(' || child.type === ')')
2500
+ continue;
2501
+ fnArgs.push(child);
2502
+ }
2503
+ if (fnArgs.length >= 2) {
2504
+ const srcArg = fnArgs[0];
2505
+ const cbArg = fnArgs[1];
2506
+ if (srcArg.type === 'identifier' &&
2507
+ !BUILTIN_GLOBALS.has(srcArg.text) &&
2508
+ cbArg.type === 'identifier' &&
2509
+ !BUILTIN_GLOBALS.has(cbArg.text)) {
2510
+ arrayCallbackBindings.push({ sourceName: srcArg.text, calleeName: cbArg.text });
2511
+ }
2512
+ }
2513
+ }
2514
+ }
2515
+ }
2516
+ /** Collection wrap: `const s = new Set(arr)` or `new Map(arr)` (variable_declarator). */
2517
+ function collectCollectionWrapBinding(node, fnRefBindings) {
2518
+ const nameN = node.childForFieldName('name');
2519
+ const valueN = node.childForFieldName('value');
2520
+ if (nameN?.type === 'identifier' && valueN?.type === 'new_expression') {
2521
+ const ctor = valueN.childForFieldName('constructor');
2522
+ const args = valueN.childForFieldName('arguments');
2523
+ if (ctor && COLLECTION_CTOR_SET.has(ctor.text) && args) {
2524
+ for (let i = 0; i < args.childCount; i++) {
2525
+ const arg = args.child(i);
2526
+ if (!arg || arg.type === '(' || arg.type === ')')
2527
+ continue;
2528
+ if (arg.type === 'identifier' && !BUILTIN_GLOBALS.has(arg.text)) {
2529
+ fnRefBindings.push({ lhs: `${nameN.text}[*]`, rhs: `${arg.text}[*]` });
2530
+ break;
2531
+ }
2532
+ }
2533
+ }
2534
+ }
2535
+ }
2536
+ /** For-of: `for (const x of arr)` (for_in_statement with an `of` keyword). */
2537
+ function collectForOfBinding(node, enclosingFunc, forOfBindings) {
2538
+ let isForOf = false;
2539
+ for (let i = 0; i < node.childCount; i++) {
2540
+ if (node.child(i)?.text === 'of') {
2541
+ isForOf = true;
2542
+ break;
2543
+ }
2544
+ }
2545
+ if (!isForOf)
2546
+ return;
2547
+ const right = node.childForFieldName('right');
2548
+ if (right?.type !== 'identifier' || BUILTIN_GLOBALS.has(right.text))
2549
+ return;
2550
+ const left = node.childForFieldName('left');
2551
+ let varName = null;
2552
+ if (left?.type === 'identifier') {
2553
+ varName = left.text;
2554
+ }
2555
+ else if (left) {
2556
+ for (let i = 0; i < left.childCount; i++) {
2557
+ const lc = left.child(i);
2558
+ if (lc?.type === 'variable_declarator') {
2559
+ const nc = lc.childForFieldName('name');
2560
+ if (nc?.type === 'identifier') {
2561
+ varName = nc.text;
2562
+ break;
2563
+ }
2564
+ }
2565
+ else if (lc?.type === 'identifier' &&
2566
+ lc.text !== 'const' &&
2567
+ lc.text !== 'let' &&
2568
+ lc.text !== 'var') {
2569
+ varName = lc.text;
2570
+ break;
2571
+ }
2572
+ }
2573
+ }
2574
+ if (varName && !BUILTIN_GLOBALS.has(varName)) {
2575
+ forOfBindings.push({ varName, sourceName: right.text, enclosingFunc });
2576
+ }
2577
+ }
2578
+ /**
2579
+ * Phase 8.3f: record object-destructuring rest-parameter bindings from function definitions.
2580
+ *
2581
+ * For each `function f({ a, ...rest })` (or arrow/function-expression equivalent),
2582
+ * records { callee: 'f', restName: 'rest', argIndex: N }. Also covers class methods
2583
+ * (`callee: 'ClassName.method'`) and object-literal methods (`callee: 'method'`).
2584
+ * The edge builder uses these to seed typeMap[rest] = { type: argName } when f(obj)
2585
+ * is called with an identifier, enabling `rest.method()` calls to resolve.
2586
+ */
2587
+ function collectObjectRestParams(node, t, currentClass, bindings) {
2588
+ let fnName = null;
2589
+ let paramsNode = null;
2590
+ if (t === 'function_declaration' || t === 'generator_function_declaration') {
2591
+ const nameN = node.childForFieldName('name');
2592
+ if (nameN?.type === 'identifier')
2593
+ fnName = nameN.text;
2594
+ paramsNode = node.childForFieldName('parameters') ?? findChild(node, 'formal_parameters');
2595
+ }
2596
+ else if (t === 'variable_declarator') {
2597
+ const nameN = node.childForFieldName('name');
2598
+ const valueN = node.childForFieldName('value');
2599
+ if (nameN?.type === 'identifier' && valueN) {
2600
+ const vt = valueN.type;
2601
+ if (vt === 'arrow_function' || vt === 'function_expression' || vt === 'generator_function') {
2602
+ fnName = nameN.text;
2603
+ paramsNode =
2604
+ valueN.childForFieldName('parameters') ?? findChild(valueN, 'formal_parameters');
2605
+ }
2606
+ }
2607
+ }
2608
+ else if (t === 'method_definition') {
2609
+ // class method: `class Foo { bar({ a, ...rest }) {} }`
2610
+ // object-literal shorthand method: `{ bar({ a, ...rest }) {} }`
2611
+ const nameN = node.childForFieldName('name');
2612
+ if (nameN) {
2613
+ fnName = currentClass ? `${currentClass}.${nameN.text}` : nameN.text;
2614
+ paramsNode = node.childForFieldName('parameters') ?? findChild(node, 'formal_parameters');
2615
+ }
2616
+ }
2617
+ else if (t === 'pair') {
2618
+ // object-literal method: `{ bar: function({ a, ...rest }) {} }`
2619
+ // Skip computed property keys (e.g. `{ [Symbol.iterator]: function({ ...rest }) {} }`)
2620
+ // because `callee: '[Symbol.iterator]'` can never match a paramBinding callee.
2621
+ const keyN = node.childForFieldName('key');
2622
+ const valueN = node.childForFieldName('value');
2623
+ if (keyN && valueN && keyN.type !== 'computed_property_name') {
2624
+ const vt = valueN.type;
2625
+ if (vt === 'arrow_function' || vt === 'function_expression' || vt === 'generator_function') {
2626
+ fnName = keyN.type === 'string' ? keyN.text.slice(1, -1) : keyN.text;
2627
+ paramsNode =
2628
+ valueN.childForFieldName('parameters') ?? findChild(valueN, 'formal_parameters');
2629
+ }
2630
+ }
2631
+ }
2632
+ if (fnName && paramsNode) {
2633
+ let paramIdx = 0;
2634
+ for (let i = 0; i < paramsNode.childCount; i++) {
2635
+ const child = paramsNode.child(i);
2636
+ if (!child)
2637
+ continue;
2638
+ const ct = child.type;
2639
+ if (ct === ',' || ct === '(' || ct === ')')
2640
+ continue;
2641
+ if (ct === 'object_pattern') {
2642
+ for (let j = 0; j < child.childCount; j++) {
2643
+ const inner = child.child(j);
2644
+ if (!inner)
2645
+ continue;
2646
+ if (inner.type === 'rest_pattern' || inner.type === 'rest_element') {
2647
+ // rest_pattern node: `...identifier` — the identifier is at child index 1
2648
+ const restId = inner.child(1) ?? inner.childForFieldName('name');
2649
+ if (restId?.type === 'identifier') {
2650
+ bindings.push({ callee: fnName, restName: restId.text, argIndex: paramIdx });
2651
+ }
2652
+ }
2653
+ }
2654
+ }
2655
+ paramIdx++;
2656
+ }
2657
+ }
2658
+ }
2659
+ /**
2660
+ * Phase 8.3f: collect object-property bindings from object literals.
2661
+ *
2662
+ * `const obj = { e4 }` → `{ objectName: "obj", propName: "e4", valueName: "e4" }`
2663
+ * `const obj = { e1: fn }` → `{ objectName: "obj", propName: "e1", valueName: "fn" }`
2664
+ *
2665
+ * Only tracks shorthand and `key: identifier` pairs; skips function literals.
2666
+ */
2667
+ function collectObjectPropBindings(node, bindings) {
2668
+ const nameN = node.childForFieldName('name');
2669
+ const valueN = node.childForFieldName('value');
2670
+ if (nameN?.type === 'identifier' && valueN?.type === 'object') {
2671
+ const objectName = nameN.text;
2672
+ for (let i = 0; i < valueN.childCount; i++) {
2673
+ const child = valueN.child(i);
2674
+ if (!child)
2675
+ continue;
2676
+ if (child.type === 'shorthand_property_identifier') {
2677
+ bindings.push({ objectName, propName: child.text, valueName: child.text });
2678
+ }
2679
+ else if (child.type === 'pair') {
2680
+ const keyN = child.childForFieldName('key');
2681
+ const valN = child.childForFieldName('value');
2682
+ if (keyN?.type === 'property_identifier' &&
2683
+ valN?.type === 'identifier' &&
2684
+ !BUILTIN_GLOBALS.has(valN.text)) {
2685
+ bindings.push({ objectName, propName: keyN.text, valueName: valN.text });
2686
+ }
2687
+ }
2688
+ }
2689
+ }
2690
+ }
2691
+ function extractReceiverName(objNode) {
2692
+ if (!objNode)
2693
+ return undefined;
2694
+ const t = objNode.type;
2695
+ if (t === 'identifier' || t === 'this' || t === 'super')
2696
+ return objNode.text;
2697
+ // `(new Foo(...)).method()` — extract the constructor name so the resolver can
2698
+ // look up `Foo.method` directly without relying on a text-based regex heuristic.
2699
+ if (t === 'new_expression') {
2700
+ const name = extractNewExprTypeName(objNode);
2701
+ if (name)
2702
+ return name;
2703
+ }
2704
+ if (t === 'parenthesized_expression') {
2705
+ // Only one level of parentheses is unwrapped here. Doubly-nested parens
2706
+ // (e.g. `((new Dog())).bark()`) and cast expressions inside parens
2707
+ // (e.g. `(new Dog() as Animal).bark()`) fall through to raw-text handling
2708
+ // below and are caught by the regex fallback in call-resolver.ts.
2709
+ for (let i = 0; i < objNode.childCount; i++) {
2710
+ const child = objNode.child(i);
2711
+ if (child?.type === 'new_expression') {
2712
+ const name = extractNewExprTypeName(child);
2713
+ if (name)
2714
+ return name;
2715
+ }
2716
+ }
2717
+ }
2718
+ return objNode.text;
2719
+ }
2720
+ function extractCallInfo(fn, callNode) {
2721
+ const fnType = fn.type;
2722
+ if (fnType === 'identifier') {
2723
+ if (fn.text === 'eval') {
2724
+ // eval(code) — dynamic code execution; capture first arg if it's a string literal
2725
+ const args = callNode.childForFieldName('arguments') || findChild(callNode, 'arguments');
2726
+ let keyExpr;
2727
+ if (args) {
2728
+ for (let i = 0; i < args.childCount; i++) {
2729
+ const child = args.child(i);
2730
+ if (!child)
2731
+ continue;
2732
+ const t = child.type;
2733
+ if (t === '(' || t === ')' || t === ',')
2734
+ continue;
2735
+ if (t === 'string' || t === 'template_string')
2736
+ keyExpr = child.text;
2737
+ break;
2738
+ }
2739
+ }
2740
+ return {
2741
+ name: '<dynamic:eval>',
2742
+ line: nodeStartLine(callNode),
2743
+ dynamic: true,
2744
+ dynamicKind: 'eval',
2745
+ keyExpr,
2746
+ };
2747
+ }
2748
+ return { name: fn.text, line: nodeStartLine(callNode) };
2749
+ }
2750
+ if (fnType === 'member_expression') {
2751
+ return extractMemberExprCallInfo(fn, callNode);
2752
+ }
2753
+ if (fnType === 'subscript_expression') {
2754
+ return extractSubscriptCallInfo(fn, callNode);
2755
+ }
2756
+ return null;
2757
+ }
2758
+ /** Return the first non-punctuation argument node from a call_expression. */
2759
+ function getFirstCallArg(callNode) {
2760
+ const args = callNode.childForFieldName('arguments') || findChild(callNode, 'arguments');
2761
+ if (!args)
2762
+ return null;
2763
+ for (let i = 0; i < args.childCount; i++) {
2764
+ const child = args.child(i);
2765
+ if (!child)
2766
+ continue;
2767
+ const t = child.type;
2768
+ if (t === '(' || t === ')' || t === ',')
2769
+ continue;
2770
+ return child;
2771
+ }
2772
+ return null;
2773
+ }
2774
+ /** Extract the logical callee from a Reflect.apply/call/construct first-arg. */
2775
+ function extractReflectCalleeFromArg(firstArg, callLine) {
2776
+ if (firstArg?.type === 'identifier') {
2777
+ return { name: firstArg.text, line: callLine, dynamic: true, dynamicKind: 'reflection' };
2778
+ }
2779
+ if (firstArg?.type === 'member_expression') {
2780
+ const innerProp = firstArg.childForFieldName('property');
2781
+ if (innerProp?.type === 'identifier') {
2782
+ return {
2783
+ name: innerProp.text,
2784
+ line: callLine,
2785
+ dynamic: true,
2786
+ dynamicKind: 'reflection',
2787
+ receiver: extractReceiverName(firstArg.childForFieldName('object')),
2788
+ };
2789
+ }
2790
+ }
2791
+ return {
2792
+ name: '<dynamic:unresolved>',
2793
+ line: callLine,
2794
+ dynamic: true,
2795
+ dynamicKind: 'unresolved-dynamic',
2796
+ };
2797
+ }
2798
+ /** Extract call info from a member_expression function node (obj.method()). */
2799
+ function extractMemberExprCallInfo(fn, callNode) {
2800
+ const obj = fn.childForFieldName('object');
2801
+ const prop = fn.childForFieldName('property');
2802
+ if (!prop)
2803
+ return null;
2804
+ const callLine = nodeStartLine(callNode);
2805
+ const propText = prop.text;
2806
+ const isReflect = obj?.type === 'identifier' && obj.text === 'Reflect';
2807
+ // Reflect.apply(fn, thisArg, args) — extract the first arg as callee
2808
+ // Note: Reflect.call does not exist in the ECMAScript spec (only Reflect.apply, construct, get, etc.)
2809
+ if (isReflect && propText === 'apply') {
2810
+ return extractReflectCalleeFromArg(getFirstCallArg(callNode), callLine);
2811
+ }
2812
+ // Reflect.construct(Target, args) — extract the constructor as the callee
2813
+ if (isReflect && propText === 'construct') {
2814
+ return extractReflectCalleeFromArg(getFirstCallArg(callNode), callLine);
2815
+ }
2816
+ // Reflect.get(target, prop) — property access via reflection
2817
+ if (isReflect && propText === 'get') {
2818
+ const args = callNode.childForFieldName('arguments') || findChild(callNode, 'arguments');
2819
+ if (args) {
2820
+ let argIdx = 0;
2821
+ let firstArg = null;
2822
+ let secondArg = null;
2823
+ for (let i = 0; i < args.childCount; i++) {
2824
+ const child = args.child(i);
2825
+ if (!child)
2826
+ continue;
2827
+ const t = child.type;
2828
+ if (t === '(' || t === ')' || t === ',')
2829
+ continue;
2830
+ if (argIdx === 0)
2831
+ firstArg = child;
2832
+ else if (argIdx === 1)
2833
+ secondArg = child;
2834
+ argIdx++;
2835
+ }
2836
+ if (secondArg) {
2837
+ const receiver = firstArg ? extractReceiverName(firstArg) : undefined;
2838
+ const st = secondArg.type;
2839
+ if (st === 'string' || st === 'string_fragment') {
2840
+ const propName = secondArg.text.replace(/['"]/g, '');
2841
+ if (propName) {
2842
+ return {
2843
+ name: propName,
2844
+ line: callLine,
2845
+ dynamic: true,
2846
+ dynamicKind: 'computed-literal',
2847
+ keyExpr: secondArg.text,
2848
+ receiver,
2849
+ };
2850
+ }
2851
+ }
2852
+ if (st === 'identifier') {
2853
+ return {
2854
+ name: '<dynamic:computed-key>',
2855
+ line: callLine,
2856
+ dynamic: true,
2857
+ dynamicKind: 'computed-key',
2858
+ keyExpr: secondArg.text,
2859
+ receiver,
2860
+ };
2861
+ }
2862
+ }
2863
+ }
2864
+ return {
2865
+ name: '<dynamic:unresolved>',
2866
+ line: callLine,
2867
+ dynamic: true,
2868
+ dynamicKind: 'unresolved-dynamic',
2869
+ };
2870
+ }
2871
+ // .call()/.apply()/.bind() — this-rebinding; target is statically known
2872
+ if (propText === 'call' || propText === 'apply' || propText === 'bind') {
2873
+ if (obj && obj.type === 'identifier')
2874
+ return { name: obj.text, line: callLine, dynamic: true, dynamicKind: 'reflection' };
2875
+ if (obj && obj.type === 'member_expression') {
2876
+ const innerProp = obj.childForFieldName('property');
2877
+ if (innerProp)
2878
+ return { name: innerProp.text, line: callLine, dynamic: true, dynamicKind: 'reflection' };
2879
+ }
2880
+ }
2881
+ // Computed string property: obj["method"]() — target is a literal; resolvable
2882
+ const propType = prop.type;
2883
+ if (propType === 'string' || propType === 'string_fragment') {
2884
+ const methodName = propText.replace(/['"]/g, '');
2885
+ if (methodName) {
2886
+ const receiver = extractReceiverName(obj);
2887
+ return {
2888
+ name: methodName,
2889
+ line: callLine,
2890
+ dynamic: true,
2891
+ dynamicKind: 'computed-literal',
2892
+ receiver,
2893
+ };
2894
+ }
2895
+ }
2896
+ const receiver = extractReceiverName(obj);
2897
+ return { name: propText, line: callLine, receiver };
2898
+ }
2899
+ /** Extract call info from a subscript_expression function node (obj[key]()). */
2900
+ function extractSubscriptCallInfo(fn, callNode) {
2901
+ const obj = fn.childForFieldName('object');
2902
+ const index = fn.childForFieldName('index');
2903
+ if (!index)
2904
+ return null;
2905
+ const indexType = index.type;
2906
+ if (indexType === 'string' || indexType === 'template_string') {
2907
+ const methodName = index.text.replace(/['"`]/g, '');
2908
+ if (methodName && !methodName.includes('$')) {
2909
+ const receiver = extractReceiverName(obj);
2910
+ return {
2911
+ name: methodName,
2912
+ line: nodeStartLine(callNode),
2913
+ dynamic: true,
2914
+ dynamicKind: 'computed-literal',
2915
+ receiver,
2916
+ };
2917
+ }
2918
+ }
2919
+ // obj[variable]() — key is a variable; may be resolvable via pts (RES-1), else flagged
2920
+ if (indexType === 'identifier') {
2921
+ const receiver = extractReceiverName(obj);
2922
+ return {
2923
+ name: '<dynamic:computed-key>',
2924
+ line: nodeStartLine(callNode),
2925
+ dynamic: true,
2926
+ dynamicKind: 'computed-key',
2927
+ keyExpr: index.text,
2928
+ receiver,
2929
+ };
2930
+ }
2931
+ // Any other index expression (binary, call, template with ${}…) — not statically resolvable
2932
+ return {
2933
+ name: '<dynamic:unresolved>',
2934
+ line: nodeStartLine(callNode),
2935
+ dynamic: true,
2936
+ dynamicKind: 'unresolved-dynamic',
2937
+ };
2938
+ }
2939
+ /**
2940
+ * Callee names that idiomatically accept callback references. Used to gate
2941
+ * member_expression args in {@link extractCallbackReferenceCalls}: arguments
2942
+ * like `user.id` are only emitted as dynamic callback calls when the callee
2943
+ * is a known callback-accepting API (router/middleware, promises, array
2944
+ * methods, event emitters, scheduling APIs). This avoids false positives
2945
+ * from plain property reads passed as data, e.g. `store.set(user.id, user)`.
2946
+ *
2947
+ * Identifier args (e.g. `router.use(handleToken)`) are always emitted — the
2948
+ * collateral damage of dropping them is larger than the FP risk, since plain
2949
+ * identifier data args rarely collide with real function names.
2950
+ */
2951
+ const CALLBACK_ACCEPTING_CALLEES = new Set([
2952
+ // Express / router / middleware
2953
+ 'use',
2954
+ 'get',
2955
+ 'post',
2956
+ 'put',
2957
+ 'delete',
2958
+ 'patch',
2959
+ 'options',
2960
+ 'head',
2961
+ 'all',
2962
+ // Promises
2963
+ 'then',
2964
+ 'catch',
2965
+ 'finally',
2966
+ // Array iteration / reduction
2967
+ 'map',
2968
+ 'filter',
2969
+ 'forEach',
2970
+ 'find',
2971
+ 'findIndex',
2972
+ 'findLast',
2973
+ 'findLastIndex',
2974
+ 'some',
2975
+ 'every',
2976
+ 'reduce',
2977
+ 'reduceRight',
2978
+ 'flatMap',
2979
+ 'sort',
2980
+ // Event emitters / DOM
2981
+ 'on',
2982
+ 'once',
2983
+ 'off',
2984
+ 'addListener',
2985
+ 'removeListener',
2986
+ 'addEventListener',
2987
+ 'removeEventListener',
2988
+ 'subscribe',
2989
+ 'unsubscribe',
2990
+ // Scheduling / plain function callbacks
2991
+ 'setTimeout',
2992
+ 'setInterval',
2993
+ 'setImmediate',
2994
+ 'queueMicrotask',
2995
+ 'requestAnimationFrame',
2996
+ 'requestIdleCallback',
2997
+ 'nextTick',
2998
+ // Commander / yargs / hooks
2999
+ 'action',
3000
+ 'command',
3001
+ ]);
3002
+ /**
3003
+ * HTTP-verb callees that double as Map/cache/repository method names (`get`,
3004
+ * `post`, `put`, `delete`, `patch`, `options`, `head`, `all`). Express/router
3005
+ * invocations always take a string-literal route path as the first argument
3006
+ * (`app.get('/path', handler)`), whereas Map-like APIs pass values/keys
3007
+ * (`cache.get(user.id)`). Requiring a string-literal first arg keeps real
3008
+ * route handlers covered while dropping the Map/cache false-positive surface.
3009
+ *
3010
+ * `use` and `all` without a path are legitimate middleware registrations, so
3011
+ * `use` is intentionally excluded here — it stays in the general allowlist.
3012
+ */
3013
+ const HTTP_VERB_CALLEES = new Set([
3014
+ 'get',
3015
+ 'post',
3016
+ 'put',
3017
+ 'delete',
3018
+ 'patch',
3019
+ 'options',
3020
+ 'head',
3021
+ 'all',
3022
+ ]);
3023
+ /**
3024
+ * Extract the callee's final name (function identifier or member expression
3025
+ * property) for callback-eligibility filtering. Returns null if the callee
3026
+ * shape is not analyzable (e.g. computed subscripts, IIFEs).
3027
+ *
3028
+ * Optional-chaining (`obj?.method(...)`) is handled transparently: in both
3029
+ * tree-sitter-javascript and tree-sitter-typescript grammars `obj?.method` is
3030
+ * still a `member_expression` (the `?.` appears as an `optional_chain` child),
3031
+ * so the property extraction below returns `method` as expected.
3032
+ */
3033
+ function extractCalleeName(callNode) {
3034
+ const fn = callNode.childForFieldName('function');
3035
+ if (!fn)
3036
+ return null;
3037
+ if (fn.type === 'identifier')
3038
+ return fn.text;
3039
+ if (fn.type === 'member_expression') {
3040
+ const prop = fn.childForFieldName('property');
3041
+ return prop ? prop.text : null;
3042
+ }
3043
+ return null;
3044
+ }
3045
+ /**
3046
+ * True iff the first argument of an arguments node is a string literal.
3047
+ * Used to distinguish Express/router route handlers (`app.get('/path', h)`)
3048
+ * from Map/cache APIs that reuse the same verb names (`cache.get(user.id)`).
3049
+ */
3050
+ function firstArgIsStringLiteral(argsNode) {
3051
+ for (let i = 0; i < argsNode.childCount; i++) {
3052
+ const child = argsNode.child(i);
3053
+ if (!child)
3054
+ continue;
3055
+ // Skip parens and commas; the first non-punctuation child is the first arg.
3056
+ if (child.type === '(' || child.type === ',' || child.type === ')')
3057
+ continue;
3058
+ return child.type === 'string' || child.type === 'template_string';
3059
+ }
3060
+ return false;
3061
+ }
3062
+ /**
3063
+ * Extract Call entries for named function references passed as arguments.
3064
+ * e.g. `router.use(handleToken, checkAuth)` yields calls to handleToken and checkAuth.
3065
+ * `app.use(auth.validate)` yields a call to validate with receiver auth.
3066
+ * Skips literals, objects, arrays, anonymous functions, and call expressions (already handled).
3067
+ *
3068
+ * To avoid false positives where plain property reads are passed as data
3069
+ * (e.g. `store.set(user.id, user)` — `user.id` is a value, not a callback),
3070
+ * member_expression args are only emitted when the callee is in
3071
+ * {@link CALLBACK_ACCEPTING_CALLEES}. Identifier args are always emitted.
3072
+ *
3073
+ * HTTP-verb callees (`get`, `post`, `put`, `delete`, `patch`, `options`,
3074
+ * `head`, `all`) double as Map/cache/repository method names, so their
3075
+ * member-expr args are only emitted when the first argument is a string
3076
+ * literal route path — matching Express/router shape and skipping
3077
+ * `cache.get(user.id)`-style calls.
3078
+ *
3079
+ * `.call()` / `.apply()` / `.bind()` — the first arg is the `this` context (not a callback of
3080
+ * the enclosing function) and subsequent args flow into the delegated function's parameters.
3081
+ * Emitting them here would produce false-positive edges from the *calling* function.
3082
+ * This-rebinding (fn::this → ctx) is handled separately by extractThisCallBindingsWalk.
3083
+ */
3084
+ function extractCallbackReferenceCalls(callNode) {
3085
+ const args = callNode.childForFieldName('arguments') || findChild(callNode, 'arguments');
3086
+ if (!args)
3087
+ return [];
3088
+ const calleeName = extractCalleeName(callNode);
3089
+ // .call() / .apply() / .bind() — the first arg is the `this` context (not a callback of
3090
+ // the enclosing function) and subsequent args flow into the delegated function's parameters.
3091
+ // Emitting them here would produce false-positive edges from the *calling* function.
3092
+ // This-rebinding (fn::this → ctx) is handled separately by extractThisCallBindingsWalk.
3093
+ if (calleeName === 'call' || calleeName === 'apply' || calleeName === 'bind')
3094
+ return [];
3095
+ let memberExprArgsAllowed = calleeName !== null && CALLBACK_ACCEPTING_CALLEES.has(calleeName);
3096
+ if (memberExprArgsAllowed && calleeName !== null && HTTP_VERB_CALLEES.has(calleeName)) {
3097
+ // HTTP verbs require a string-literal route path to be treated as a
3098
+ // callback-accepting API; otherwise `cache.get(user.id)` etc. would
3099
+ // still emit `id` as a dynamic call.
3100
+ memberExprArgsAllowed = firstArgIsStringLiteral(args);
3101
+ }
3102
+ const result = [];
3103
+ const callLine = nodeStartLine(callNode);
3104
+ for (let i = 0; i < args.childCount; i++) {
3105
+ const child = args.child(i);
3106
+ if (!child)
3107
+ continue;
3108
+ if (child.type === 'identifier') {
3109
+ result.push({ name: child.text, line: callLine, dynamic: true });
3110
+ }
3111
+ else if (child.type === 'member_expression' && memberExprArgsAllowed) {
3112
+ const prop = child.childForFieldName('property');
3113
+ const obj = child.childForFieldName('object');
3114
+ if (prop) {
3115
+ const receiver = extractReceiverName(obj);
3116
+ result.push({ name: prop.text, line: callLine, dynamic: true, receiver });
3117
+ }
3118
+ }
3119
+ }
3120
+ return result;
3121
+ }
3122
+ /**
3123
+ * Collect, from a call_expression node:
3124
+ * - `this(args)` call expressions → `{name: 'this', ...}` entries in `calls`
3125
+ * (where `this` is used as a function, not as a receiver)
3126
+ * - `fn.call(namedCtx, ...)` / `fn.apply(namedCtx, ...)` bindings →
3127
+ * `{ callee: 'fn', thisArg: 'namedCtx' }` entries in `thisCallBindings`
3128
+ */
3129
+ function collectThisCallAndBindings(node, calls, thisCallBindings) {
3130
+ const fn = node.childForFieldName('function');
3131
+ if (fn?.type === 'this') {
3132
+ calls.push({ name: 'this', line: nodeStartLine(node) });
3133
+ }
3134
+ else if (fn?.type === 'member_expression') {
3135
+ const obj = fn.childForFieldName('object');
3136
+ const prop = fn.childForFieldName('property');
3137
+ if (obj?.type === 'identifier' &&
3138
+ prop &&
3139
+ (prop.text === 'call' || prop.text === 'apply') &&
3140
+ !BUILTIN_GLOBALS.has(obj.text)) {
3141
+ const args = node.childForFieldName('arguments') || findChild(node, 'arguments');
3142
+ if (args) {
3143
+ for (let i = 0; i < args.childCount; i++) {
3144
+ const child = args.child(i);
3145
+ if (!child)
3146
+ continue;
3147
+ const t = child.type;
3148
+ if (t === '(' || t === ')' || t === ',')
3149
+ continue;
3150
+ // First real argument: only bind if it's a plain identifier
3151
+ if (t === 'identifier' &&
3152
+ !BUILTIN_GLOBALS.has(child.text) &&
3153
+ child.text !== 'undefined' &&
3154
+ child.text !== 'null') {
3155
+ thisCallBindings.push({ callee: obj.text, thisArg: child.text });
3156
+ }
3157
+ break;
3158
+ }
3159
+ }
3160
+ }
3161
+ }
3162
+ }
3163
+ /**
3164
+ * Single-pass collector walk: one DFS that dispatches each node to every
3165
+ * collector interested in its type.
3166
+ *
3167
+ * This replaces what had grown to ten independent full-tree traversals (one
3168
+ * per collector). On WASM trees every node access (`child(i)`, `.type`,
3169
+ * `childForFieldName`) marshals through the JS↔WASM boundary, so traversal
3170
+ * count — not collector work — dominated extraction cost: the accumulated
3171
+ * per-collector walks made extraction ~2.4× slower between v3.11.2 and
3172
+ * v3.12.0 (7.5 → 17.7 ms/file on codegraph's own corpus).
3173
+ *
3174
+ * Collectors with bespoke traversal semantics stay separate:
3175
+ * - extractConstantsWalk / extractDestructuredBindingsWalk prune function
3176
+ * scopes and unwrap export statements on the way down;
3177
+ * - extractReturnTypeMapWalk / extractTypeMapWalk / extractSpreadForOfWalk /
3178
+ * extractObjectRestParamBindingsWalk thread enclosing-class context with
3179
+ * per-walk reset rules that intentionally differ (see each walk's comments).
3180
+ */
3181
+ function runCollectorWalk(rootNode, targets) {
3182
+ const walk = (node, depth, inDynamicImport) => {
3183
+ if (depth >= MAX_WALK_DEPTH)
3184
+ return;
3185
+ let childInDynamicImport = inDynamicImport;
3186
+ switch (node.type) {
3187
+ case 'call_expression': {
3188
+ // Matched import() calls suppress *dynamic-import* collection in their
3189
+ // argument subtree (mirrors the old walk's early return) while leaving
3190
+ // the subtree visible to every other collector. The !inDynamicImport
3191
+ // check runs first so nested import() calls are neither collected nor
3192
+ // re-matched.
3193
+ if (targets.imports && !inDynamicImport && collectDynamicImport(node, targets.imports)) {
3194
+ childInDynamicImport = true;
3195
+ }
3196
+ if (targets.calls && targets.thisCallBindings) {
3197
+ collectThisCallAndBindings(node, targets.calls, targets.thisCallBindings);
3198
+ }
3199
+ collectParamBindings(node, targets.paramBindings);
3200
+ collectDefinePropertyReceiver(node, targets.definePropertyReceivers);
3201
+ break;
3202
+ }
3203
+ case 'variable_declarator':
3204
+ collectArrayElemBindings(node, targets.arrayElemBindings);
3205
+ collectObjectPropBindings(node, targets.objectPropBindings);
3206
+ break;
3207
+ case 'expression_statement': {
3208
+ const expr = node.child(0);
3209
+ if (expr?.type === 'assignment_expression') {
3210
+ const lhs = expr.childForFieldName('left');
3211
+ const rhs = expr.childForFieldName('right');
3212
+ if (lhs && rhs) {
3213
+ handlePrototypeAssignment(lhs, rhs, targets.definitions, targets.typeMap);
3214
+ if (targets.funcPropDefs)
3215
+ handleFuncPropAssignment(lhs, rhs, targets.funcPropDefs);
3216
+ }
3217
+ }
3218
+ break;
3219
+ }
3220
+ case 'new_expression': {
3221
+ const name = extractNewExprTypeName(node);
3222
+ if (name)
3223
+ targets.newExpressions.push(name);
3224
+ break;
3225
+ }
3226
+ case 'decorator': {
3227
+ if (targets.calls)
3228
+ handleDecorator(node, targets.calls);
3229
+ break;
3230
+ }
3231
+ case 'field_definition':
3232
+ case 'public_field_definition':
3233
+ if (targets.classMemberDefs)
3234
+ handleFieldDef(node, targets.classMemberDefs);
3235
+ break;
3236
+ case 'class_static_block':
3237
+ if (targets.classMemberDefs)
3238
+ handleStaticBlock(node, targets.classMemberDefs);
3239
+ break;
3240
+ }
3241
+ for (let i = 0; i < node.childCount; i++) {
3242
+ walk(node.child(i), depth + 1, childInDynamicImport);
3243
+ }
3244
+ };
3245
+ walk(rootNode, 0, false);
3246
+ }
3247
+ function findAnonymousCallback(argsNode) {
3248
+ for (let i = 0; i < argsNode.childCount; i++) {
3249
+ const child = argsNode.child(i);
3250
+ if (child && (child.type === 'arrow_function' || child.type === 'function_expression')) {
3251
+ return child;
3252
+ }
3253
+ }
3254
+ return null;
3255
+ }
3256
+ function findFirstStringArg(argsNode) {
3257
+ for (let i = 0; i < argsNode.childCount; i++) {
3258
+ const child = argsNode.child(i);
3259
+ if (child && child.type === 'string') {
3260
+ return child.text.replace(/['"]/g, '');
3261
+ }
3262
+ }
3263
+ return null;
3264
+ }
3265
+ function walkCallChain(startNode, methodName) {
3266
+ let current = startNode;
3267
+ while (current) {
3268
+ const curType = current.type;
3269
+ if (curType === 'call_expression') {
3270
+ const fn = current.childForFieldName('function');
3271
+ if (fn && fn.type === 'member_expression') {
3272
+ const prop = fn.childForFieldName('property');
3273
+ if (prop && prop.text === methodName) {
3274
+ return current;
3275
+ }
3276
+ }
3277
+ current = fn;
3278
+ }
3279
+ else if (curType === 'member_expression') {
3280
+ current = current.childForFieldName('object');
3281
+ }
3282
+ else {
3283
+ break;
3284
+ }
3285
+ }
3286
+ return null;
3287
+ }
3288
+ const EXPRESS_METHODS = new Set([
3289
+ 'get',
3290
+ 'post',
3291
+ 'put',
3292
+ 'delete',
3293
+ 'patch',
3294
+ 'options',
3295
+ 'head',
3296
+ 'all',
3297
+ 'use',
3298
+ ]);
3299
+ const EVENT_METHODS = new Set(['on', 'once', 'addEventListener', 'addListener']);
3300
+ function extractCallbackDefinition(callNode, fn) {
3301
+ if (!fn)
3302
+ fn = callNode.childForFieldName('function');
3303
+ if (fn?.type !== 'member_expression')
3304
+ return null;
3305
+ const prop = fn.childForFieldName('property');
3306
+ if (!prop)
3307
+ return null;
3308
+ const method = prop.text;
3309
+ const args = callNode.childForFieldName('arguments') || findChild(callNode, 'arguments');
3310
+ if (!args)
3311
+ return null;
3312
+ // Commander: .action(callback) with .command('name') in chain
3313
+ if (method === 'action') {
3314
+ const cb = findAnonymousCallback(args);
3315
+ if (!cb)
3316
+ return null;
3317
+ const commandCall = walkCallChain(fn.childForFieldName('object'), 'command');
3318
+ if (!commandCall)
3319
+ return null;
3320
+ const cmdArgs = commandCall.childForFieldName('arguments') || findChild(commandCall, 'arguments');
3321
+ if (!cmdArgs)
3322
+ return null;
3323
+ const cmdName = findFirstStringArg(cmdArgs);
3324
+ if (!cmdName)
3325
+ return null;
3326
+ const firstWord = cmdName.split(/\s/)[0];
3327
+ return {
3328
+ name: `command:${firstWord}`,
3329
+ kind: 'function',
3330
+ line: nodeStartLine(cb),
3331
+ endLine: nodeEndLine(cb),
3332
+ };
3333
+ }
3334
+ // Express: app.get('/path', callback)
3335
+ if (EXPRESS_METHODS.has(method)) {
3336
+ const strArg = findFirstStringArg(args);
3337
+ if (!strArg?.startsWith('/'))
3338
+ return null;
3339
+ const cb = findAnonymousCallback(args);
3340
+ if (!cb)
3341
+ return null;
3342
+ return {
3343
+ name: `route:${method.toUpperCase()} ${strArg}`,
3344
+ kind: 'function',
3345
+ line: nodeStartLine(cb),
3346
+ endLine: nodeEndLine(cb),
3347
+ };
3348
+ }
3349
+ // Events: emitter.on('event', callback)
3350
+ if (EVENT_METHODS.has(method)) {
3351
+ const eventName = findFirstStringArg(args);
3352
+ if (!eventName)
3353
+ return null;
3354
+ const cb = findAnonymousCallback(args);
3355
+ if (!cb)
3356
+ return null;
3357
+ return {
3358
+ name: `event:${eventName}`,
3359
+ kind: 'function',
3360
+ line: nodeStartLine(cb),
3361
+ endLine: nodeEndLine(cb),
3362
+ };
3363
+ }
3364
+ return null;
3365
+ }
3366
+ function extractSuperclass(heritage) {
3367
+ for (let i = 0; i < heritage.childCount; i++) {
3368
+ const child = heritage.child(i);
3369
+ if (child.type === 'identifier')
3370
+ return child.text;
3371
+ if (child.type === 'member_expression')
3372
+ return child.text;
3373
+ const found = extractSuperclass(child);
3374
+ if (found)
3375
+ return found;
3376
+ }
3377
+ return null;
3378
+ }
3379
+ const JS_CLASS_TYPES = ['class_declaration', 'abstract_class_declaration', 'class'];
3380
+ function findParentClass(node) {
3381
+ return findParentNode(node, JS_CLASS_TYPES);
3382
+ }
3383
+ function extractImportNames(node) {
3384
+ const names = [];
3385
+ function scan(n) {
3386
+ if (n.type === 'import_specifier' || n.type === 'export_specifier') {
3387
+ const nameNode = n.childForFieldName('name') || n.childForFieldName('alias');
3388
+ if (nameNode)
3389
+ names.push(nameNode.text);
3390
+ else
3391
+ names.push(n.text);
3392
+ }
3393
+ else if (n.type === 'identifier' && n.parent && n.parent.type === 'import_clause') {
3394
+ names.push(n.text);
3395
+ }
3396
+ else if (n.type === 'namespace_import') {
3397
+ names.push(n.text);
3398
+ }
3399
+ for (let i = 0; i < n.childCount; i++)
3400
+ scan(n.child(i));
3401
+ }
3402
+ scan(node);
3403
+ return names;
3404
+ }
3405
+ /**
3406
+ * Extract destructured names from a dynamic import() call expression.
3407
+ *
3408
+ * Handles:
3409
+ * const { a, b } = await import('./foo.js') → ['a', 'b']
3410
+ * const mod = await import('./foo.js') → ['mod']
3411
+ * import('./foo.js') → [] (no names extractable)
3412
+ *
3413
+ * Walks up the AST from the call_expression to find the enclosing
3414
+ * variable_declarator and reads the name/object_pattern.
3415
+ */
3416
+ function extractDynamicImportNames(callNode) {
3417
+ // Walk up: call_expression → await_expression → variable_declarator
3418
+ let current = callNode.parent;
3419
+ // Skip await_expression wrapper if present
3420
+ if (current && current.type === 'await_expression')
3421
+ current = current.parent;
3422
+ // We should now be at a variable_declarator (or not, if standalone import())
3423
+ if (current?.type !== 'variable_declarator')
3424
+ return [];
3425
+ const nameNode = current.childForFieldName('name');
3426
+ if (!nameNode)
3427
+ return [];
3428
+ // const { a, b } = await import(...) → object_pattern
3429
+ if (nameNode.type === 'object_pattern') {
3430
+ const names = [];
3431
+ for (let i = 0; i < nameNode.childCount; i++) {
3432
+ const child = nameNode.child(i);
3433
+ if (child.type === 'shorthand_property_identifier_pattern') {
3434
+ names.push(child.text);
3435
+ }
3436
+ else if (child.type === 'pair_pattern') {
3437
+ // { a: localName } → use localName (the alias) for the local binding,
3438
+ // but use the key (original name) for import resolution
3439
+ const key = child.childForFieldName('key');
3440
+ if (key)
3441
+ names.push(key.text);
3442
+ }
3443
+ }
3444
+ return names;
3445
+ }
3446
+ // const mod = await import(...) → identifier (namespace-like import)
3447
+ if (nameNode.type === 'identifier') {
3448
+ return [nameNode.text];
3449
+ }
3450
+ // const [a, b] = await import(...) → array_pattern (rare but possible)
3451
+ if (nameNode.type === 'array_pattern') {
3452
+ const names = [];
3453
+ for (let i = 0; i < nameNode.childCount; i++) {
3454
+ const child = nameNode.child(i);
3455
+ if (child.type === 'identifier')
3456
+ names.push(child.text);
3457
+ else if (child.type === 'rest_pattern') {
3458
+ const inner = child.child(0) || child.childForFieldName('name');
3459
+ if (inner && inner.type === 'identifier')
3460
+ names.push(inner.text);
3461
+ }
3462
+ }
3463
+ return names;
3464
+ }
3465
+ return [];
3466
+ }
3467
+ // ── Phase 8.X: Prototype-based method extraction ────────────────────────────
3468
+ /**
3469
+ * Walk the AST and extract prototype-based method definitions and aliases.
3470
+ *
3471
+ * Handles three patterns:
3472
+ * 1. `Foo.prototype.bar = function(){...}` — emits Foo.bar as method definition
3473
+ * 2. `Foo.prototype.bar = identifier` — sets typeMap['Foo.bar'] = { type: identifier }
3474
+ * 3. `Foo.prototype = { bar: fn, ... }` — emits defs and typeMap entries per property
3475
+ *
3476
+ * Emitting definitions under the canonical `ClassName.methodName` name lets the
3477
+ * existing typeMap-based call resolver find them when a typed receiver dispatches
3478
+ * `instance.method()` (lookup.byName('C.foo') in resolveByMethodOrGlobal).
3479
+ *
3480
+ * typeMap entries for identifier aliases (`Foo.bar → { type: 'someId' }`) are
3481
+ * consumed by the prototype-alias fallback added to resolveByMethodOrGlobal.
3482
+ */
3483
+ // Prototype-method assignments (`Foo.prototype.bar = fn`) are collected inline
3484
+ // in runCollectorWalk's expression_statement case via handlePrototypeAssignment.
3485
+ /**
3486
+ * Handle an assignment_expression that may be a prototype assignment.
3487
+ *
3488
+ * Matches:
3489
+ * - `Foo.prototype.bar = rhs` (lhs ends in .prototype.bar)
3490
+ * - `Foo.prototype = { ... }` (lhs ends in .prototype, rhs is object literal)
3491
+ */
3492
+ function handlePrototypeAssignment(lhs, rhs, definitions, typeMap) {
3493
+ if (lhs.type !== 'member_expression')
3494
+ return;
3495
+ const lhsObj = lhs.childForFieldName('object');
3496
+ const lhsProp = lhs.childForFieldName('property');
3497
+ if (!lhsObj || !lhsProp)
3498
+ return;
3499
+ // Pattern 1: `Foo.prototype.bar = rhs`
3500
+ // lhs.object is `Foo.prototype` (member_expression), lhs.property is `bar`
3501
+ if (lhsObj.type === 'member_expression' &&
3502
+ (lhsProp.type === 'property_identifier' || lhsProp.type === 'identifier')) {
3503
+ const protoObj = lhsObj.childForFieldName('object');
3504
+ const protoProp = lhsObj.childForFieldName('property');
3505
+ if (protoObj?.type === 'identifier' &&
3506
+ protoProp?.text === 'prototype' &&
3507
+ !BUILTIN_GLOBALS.has(protoObj.text)) {
3508
+ emitPrototypeMethod(protoObj.text, lhsProp.text, rhs, definitions, typeMap);
3509
+ }
3510
+ return;
3511
+ }
3512
+ // Pattern 2: `Foo.prototype = { bar: fn, ... }`
3513
+ // lhs.object is `Foo` (identifier), lhs.property is `prototype`
3514
+ if (lhsObj.type === 'identifier' &&
3515
+ lhsProp.text === 'prototype' &&
3516
+ !BUILTIN_GLOBALS.has(lhsObj.text) &&
3517
+ rhs.type === 'object') {
3518
+ extractPrototypeObjectLiteral(lhsObj.text, rhs, definitions, typeMap);
3519
+ }
3520
+ }
3521
+ /** Emit one prototype method definition or typeMap alias for `ClassName.methodName = rhs`. */
3522
+ function emitPrototypeMethod(className, methodName, rhs, definitions, typeMap) {
3523
+ const fullName = `${className}.${methodName}`;
3524
+ if (rhs.type === 'function_expression' || rhs.type === 'arrow_function') {
3525
+ const params = extractParameters(rhs);
3526
+ definitions.push({
3527
+ name: fullName,
3528
+ kind: 'method',
3529
+ line: nodeStartLine(rhs),
3530
+ endLine: nodeEndLine(rhs),
3531
+ children: params.length > 0 ? params : undefined,
3532
+ });
3533
+ }
3534
+ else if (rhs.type === 'identifier' && !BUILTIN_GLOBALS.has(rhs.text)) {
3535
+ // Prototype alias: `A.prototype.t = f` → typeMap['A.t'] = { type: 'f' }
3536
+ // Consumed by the prototype-alias fallback in resolveByMethodOrGlobal.
3537
+ setTypeMapEntry(typeMap, fullName, rhs.text, 0.9);
3538
+ }
3539
+ }
3540
+ /**
3541
+ * Extract function-as-object property method definitions.
3542
+ *
3543
+ * Handles `fn.method = function() {}` and `fn.method = () => {}` patterns.
3544
+ * Emits a `method` definition named `fn.method` so that:
3545
+ * 1. `findCaller` attributes calls inside the body to `fn.method`
3546
+ * 2. `resolveByMethodOrGlobal` resolves `this.other()` inside `fn.method` to `fn.other`
3547
+ *
3548
+ * Excludes BUILTIN_GLOBALS objects and `.prototype` (handled by extractPrototypeMethodsWalk).
3549
+ */
3550
+ // Function-as-object-property assignments (`fn.method = function(){}`) are
3551
+ // collected inline in runCollectorWalk's expression_statement case (walk path
3552
+ // only — the query path captures them via the `assign_left`/`assign_right`
3553
+ // query pattern in dispatchQueryMatch).
3554
+ function handleFuncPropAssignment(lhs, rhs, definitions) {
3555
+ if (lhs.type !== 'member_expression')
3556
+ return;
3557
+ if (rhs.type !== 'function_expression' && rhs.type !== 'arrow_function')
3558
+ return;
3559
+ const obj = lhs.childForFieldName('object');
3560
+ const prop = lhs.childForFieldName('property');
3561
+ if (!obj || !prop)
3562
+ return;
3563
+ if (obj.type !== 'identifier')
3564
+ return;
3565
+ if (prop.type !== 'property_identifier' && prop.type !== 'identifier')
3566
+ return;
3567
+ if (BUILTIN_GLOBALS.has(obj.text))
3568
+ return;
3569
+ if (prop.text === 'prototype')
3570
+ return;
3571
+ const params = extractParameters(rhs);
3572
+ definitions.push({
3573
+ name: `${obj.text}.${prop.text}`,
3574
+ kind: 'method',
3575
+ line: nodeStartLine(rhs),
3576
+ endLine: nodeEndLine(rhs),
3577
+ children: params.length > 0 ? params : undefined,
3578
+ });
3579
+ }
3580
+ /** Iterate over an object literal assigned to `Foo.prototype` and emit defs/aliases. */
3581
+ function extractPrototypeObjectLiteral(className, objNode, definitions, typeMap) {
3582
+ for (let i = 0; i < objNode.childCount; i++) {
3583
+ const child = objNode.child(i);
3584
+ if (!child)
3585
+ continue;
3586
+ if (child.type === 'method_definition') {
3587
+ // Shorthand method: `Foo.prototype = { bar() {} }`
3588
+ const nameNode = child.childForFieldName('name');
3589
+ if (nameNode) {
3590
+ definitions.push({
3591
+ name: `${className}.${nameNode.text}`,
3592
+ kind: 'method',
3593
+ line: nodeStartLine(child),
3594
+ endLine: nodeEndLine(child),
3595
+ });
3596
+ }
3597
+ continue;
3598
+ }
3599
+ if (child.type === 'shorthand_property_identifier') {
3600
+ // ES6 shorthand: `Foo.prototype = { bar }` → alias typeMap['Foo.bar'] = { type: 'bar' }
3601
+ if (!BUILTIN_GLOBALS.has(child.text)) {
3602
+ setTypeMapEntry(typeMap, `${className}.${child.text}`, child.text, 0.9);
3603
+ }
3604
+ continue;
3605
+ }
3606
+ if (child.type !== 'pair')
3607
+ continue;
3608
+ const keyNode = child.childForFieldName('key');
3609
+ const valueNode = child.childForFieldName('value');
3610
+ if (!keyNode || !valueNode)
3611
+ continue;
3612
+ const methodName = keyNode.type === 'string' ? keyNode.text.replace(/['"]/g, '') : keyNode.text;
3613
+ if (!methodName)
3614
+ continue;
3615
+ emitPrototypeMethod(className, methodName, valueNode, definitions, typeMap);
3616
+ }
3617
+ }
3618
+ //# sourceMappingURL=javascript.js.map