@aroman22/codegraph-vba-darwin-arm64 1.5.2 → 1.6.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 (335) hide show
  1. package/bin/codegraph +5 -0
  2. package/lib/dist/bin/codegraph.d.ts +1 -1
  3. package/lib/dist/bin/codegraph.d.ts.map +1 -1
  4. package/lib/dist/bin/codegraph.js +307 -81
  5. package/lib/dist/bin/codegraph.js.map +1 -1
  6. package/lib/dist/bin/command-supervision.d.ts +38 -1
  7. package/lib/dist/bin/command-supervision.d.ts.map +1 -1
  8. package/lib/dist/bin/command-supervision.js +22 -3
  9. package/lib/dist/bin/command-supervision.js.map +1 -1
  10. package/lib/dist/db/index.d.ts +84 -5
  11. package/lib/dist/db/index.d.ts.map +1 -1
  12. package/lib/dist/db/index.js +209 -12
  13. package/lib/dist/db/index.js.map +1 -1
  14. package/lib/dist/db/migrations.d.ts +1 -1
  15. package/lib/dist/db/migrations.d.ts.map +1 -1
  16. package/lib/dist/db/migrations.js +80 -3
  17. package/lib/dist/db/migrations.js.map +1 -1
  18. package/lib/dist/db/queries.d.ts +116 -4
  19. package/lib/dist/db/queries.d.ts.map +1 -1
  20. package/lib/dist/db/queries.js +294 -7
  21. package/lib/dist/db/queries.js.map +1 -1
  22. package/lib/dist/db/schema.sql +43 -1
  23. package/lib/dist/db/wal-valve.d.ts +106 -0
  24. package/lib/dist/db/wal-valve.d.ts.map +1 -0
  25. package/lib/dist/db/wal-valve.js +208 -0
  26. package/lib/dist/db/wal-valve.js.map +1 -0
  27. package/lib/dist/directory.d.ts +9 -5
  28. package/lib/dist/directory.d.ts.map +1 -1
  29. package/lib/dist/directory.js +210 -19
  30. package/lib/dist/directory.js.map +1 -1
  31. package/lib/dist/extraction/cfml-extractor.d.ts +107 -0
  32. package/lib/dist/extraction/cfml-extractor.d.ts.map +1 -0
  33. package/lib/dist/extraction/cfml-extractor.js +494 -0
  34. package/lib/dist/extraction/cfml-extractor.js.map +1 -0
  35. package/lib/dist/extraction/grammars.d.ts +25 -1
  36. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  37. package/lib/dist/extraction/grammars.js +177 -23
  38. package/lib/dist/extraction/grammars.js.map +1 -1
  39. package/lib/dist/extraction/index.d.ts +47 -2
  40. package/lib/dist/extraction/index.d.ts.map +1 -1
  41. package/lib/dist/extraction/index.js +568 -51
  42. package/lib/dist/extraction/index.js.map +1 -1
  43. package/lib/dist/extraction/languages/arkts.d.ts +3 -0
  44. package/lib/dist/extraction/languages/arkts.d.ts.map +1 -0
  45. package/lib/dist/extraction/languages/arkts.js +127 -0
  46. package/lib/dist/extraction/languages/arkts.js.map +1 -0
  47. package/lib/dist/extraction/languages/c-cpp.d.ts +98 -0
  48. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  49. package/lib/dist/extraction/languages/c-cpp.js +563 -1
  50. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  51. package/lib/dist/extraction/languages/cfquery.d.ts +12 -0
  52. package/lib/dist/extraction/languages/cfquery.d.ts.map +1 -0
  53. package/lib/dist/extraction/languages/cfquery.js +28 -0
  54. package/lib/dist/extraction/languages/cfquery.js.map +1 -0
  55. package/lib/dist/extraction/languages/cfscript.d.ts +3 -0
  56. package/lib/dist/extraction/languages/cfscript.d.ts.map +1 -0
  57. package/lib/dist/extraction/languages/cfscript.js +73 -0
  58. package/lib/dist/extraction/languages/cfscript.js.map +1 -0
  59. package/lib/dist/extraction/languages/cobol.d.ts +33 -0
  60. package/lib/dist/extraction/languages/cobol.d.ts.map +1 -0
  61. package/lib/dist/extraction/languages/cobol.js +499 -0
  62. package/lib/dist/extraction/languages/cobol.js.map +1 -0
  63. package/lib/dist/extraction/languages/erlang.d.ts +3 -0
  64. package/lib/dist/extraction/languages/erlang.d.ts.map +1 -0
  65. package/lib/dist/extraction/languages/erlang.js +350 -0
  66. package/lib/dist/extraction/languages/erlang.js.map +1 -0
  67. package/lib/dist/extraction/languages/index.d.ts.map +1 -1
  68. package/lib/dist/extraction/languages/index.js +18 -0
  69. package/lib/dist/extraction/languages/index.js.map +1 -1
  70. package/lib/dist/extraction/languages/nix.d.ts +3 -0
  71. package/lib/dist/extraction/languages/nix.d.ts.map +1 -0
  72. package/lib/dist/extraction/languages/nix.js +294 -0
  73. package/lib/dist/extraction/languages/nix.js.map +1 -0
  74. package/lib/dist/extraction/languages/solidity.d.ts +3 -0
  75. package/lib/dist/extraction/languages/solidity.d.ts.map +1 -0
  76. package/lib/dist/extraction/languages/solidity.js +293 -0
  77. package/lib/dist/extraction/languages/solidity.js.map +1 -0
  78. package/lib/dist/extraction/languages/terraform.d.ts +3 -0
  79. package/lib/dist/extraction/languages/terraform.d.ts.map +1 -0
  80. package/lib/dist/extraction/languages/terraform.js +641 -0
  81. package/lib/dist/extraction/languages/terraform.js.map +1 -0
  82. package/lib/dist/extraction/languages/vbnet.d.ts +11 -0
  83. package/lib/dist/extraction/languages/vbnet.d.ts.map +1 -0
  84. package/lib/dist/extraction/languages/vbnet.js +141 -0
  85. package/lib/dist/extraction/languages/vbnet.js.map +1 -0
  86. package/lib/dist/extraction/mybatis-extractor.d.ts +30 -10
  87. package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -1
  88. package/lib/dist/extraction/mybatis-extractor.js +140 -38
  89. package/lib/dist/extraction/mybatis-extractor.js.map +1 -1
  90. package/lib/dist/extraction/parse-pool.d.ts +28 -1
  91. package/lib/dist/extraction/parse-pool.d.ts.map +1 -1
  92. package/lib/dist/extraction/parse-pool.js +76 -7
  93. package/lib/dist/extraction/parse-pool.js.map +1 -1
  94. package/lib/dist/extraction/parse-worker.js +11 -4
  95. package/lib/dist/extraction/parse-worker.js.map +1 -1
  96. package/lib/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
  97. package/lib/dist/extraction/tree-sitter-helpers.js +1 -0
  98. package/lib/dist/extraction/tree-sitter-helpers.js.map +1 -1
  99. package/lib/dist/extraction/tree-sitter-types.d.ts +20 -1
  100. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  101. package/lib/dist/extraction/tree-sitter.d.ts +60 -1
  102. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  103. package/lib/dist/extraction/tree-sitter.js +905 -20
  104. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  105. package/lib/dist/extraction/vba/call-sweep.d.ts +3 -0
  106. package/lib/dist/extraction/vba/call-sweep.d.ts.map +1 -0
  107. package/lib/dist/extraction/vba/call-sweep.js +206 -0
  108. package/lib/dist/extraction/vba/call-sweep.js.map +1 -0
  109. package/lib/dist/extraction/vba/calls.d.ts +55 -0
  110. package/lib/dist/extraction/vba/calls.d.ts.map +1 -0
  111. package/lib/dist/extraction/vba/calls.js +439 -0
  112. package/lib/dist/extraction/vba/calls.js.map +1 -0
  113. package/lib/dist/extraction/vba/constants.d.ts +42 -0
  114. package/lib/dist/extraction/vba/constants.d.ts.map +1 -0
  115. package/lib/dist/extraction/vba/constants.js +112 -0
  116. package/lib/dist/extraction/vba/constants.js.map +1 -0
  117. package/lib/dist/extraction/vba/context.d.ts +175 -0
  118. package/lib/dist/extraction/vba/context.d.ts.map +1 -0
  119. package/lib/dist/extraction/vba/context.js +268 -0
  120. package/lib/dist/extraction/vba/context.js.map +1 -0
  121. package/lib/dist/extraction/vba/controls.d.ts +24 -0
  122. package/lib/dist/extraction/vba/controls.d.ts.map +1 -0
  123. package/lib/dist/extraction/vba/controls.js +89 -0
  124. package/lib/dist/extraction/vba/controls.js.map +1 -0
  125. package/lib/dist/extraction/vba/declarations.d.ts +3 -0
  126. package/lib/dist/extraction/vba/declarations.d.ts.map +1 -0
  127. package/lib/dist/extraction/vba/declarations.js +154 -0
  128. package/lib/dist/extraction/vba/declarations.js.map +1 -0
  129. package/lib/dist/extraction/vba/dims.d.ts +3 -0
  130. package/lib/dist/extraction/vba/dims.d.ts.map +1 -0
  131. package/lib/dist/extraction/vba/dims.js +186 -0
  132. package/lib/dist/extraction/vba/dims.js.map +1 -0
  133. package/lib/dist/extraction/vba/docmd.d.ts +16 -0
  134. package/lib/dist/extraction/vba/docmd.d.ts.map +1 -0
  135. package/lib/dist/extraction/vba/docmd.js +179 -0
  136. package/lib/dist/extraction/vba/docmd.js.map +1 -0
  137. package/lib/dist/extraction/vba/enums-consts.d.ts +15 -0
  138. package/lib/dist/extraction/vba/enums-consts.d.ts.map +1 -0
  139. package/lib/dist/extraction/vba/enums-consts.js +178 -0
  140. package/lib/dist/extraction/vba/enums-consts.js.map +1 -0
  141. package/lib/dist/extraction/vba/implements.d.ts +3 -0
  142. package/lib/dist/extraction/vba/implements.d.ts.map +1 -0
  143. package/lib/dist/extraction/vba/implements.js +52 -0
  144. package/lib/dist/extraction/vba/implements.js.map +1 -0
  145. package/lib/dist/extraction/vba/procedures.d.ts +3 -0
  146. package/lib/dist/extraction/vba/procedures.d.ts.map +1 -0
  147. package/lib/dist/extraction/vba/procedures.js +239 -0
  148. package/lib/dist/extraction/vba/procedures.js.map +1 -0
  149. package/lib/dist/extraction/vba/sql-wrapper.d.ts +17 -0
  150. package/lib/dist/extraction/vba/sql-wrapper.d.ts.map +1 -0
  151. package/lib/dist/extraction/vba/sql-wrapper.js +212 -0
  152. package/lib/dist/extraction/vba/sql-wrapper.js.map +1 -0
  153. package/lib/dist/extraction/vba/tempvars.d.ts +10 -0
  154. package/lib/dist/extraction/vba/tempvars.d.ts.map +1 -0
  155. package/lib/dist/extraction/vba/tempvars.js +138 -0
  156. package/lib/dist/extraction/vba/tempvars.js.map +1 -0
  157. package/lib/dist/extraction/vba/text-utils.d.ts +73 -0
  158. package/lib/dist/extraction/vba/text-utils.d.ts.map +1 -0
  159. package/lib/dist/extraction/vba/text-utils.js +195 -0
  160. package/lib/dist/extraction/vba/text-utils.js.map +1 -0
  161. package/lib/dist/extraction/vba-extractor.d.ts +3 -951
  162. package/lib/dist/extraction/vba-extractor.d.ts.map +1 -1
  163. package/lib/dist/extraction/vba-extractor.js +46 -2934
  164. package/lib/dist/extraction/vba-extractor.js.map +1 -1
  165. package/lib/dist/extraction/vba-preprocess.d.ts +1 -1
  166. package/lib/dist/extraction/vba-preprocess.d.ts.map +1 -1
  167. package/lib/dist/extraction/vba-preprocess.js +300 -88
  168. package/lib/dist/extraction/vba-preprocess.js.map +1 -1
  169. package/lib/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  170. package/lib/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  171. package/lib/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  172. package/lib/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  173. package/lib/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  174. package/lib/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  175. package/lib/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  176. package/lib/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
  177. package/lib/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  178. package/lib/dist/graph/traversal.d.ts.map +1 -1
  179. package/lib/dist/graph/traversal.js +76 -17
  180. package/lib/dist/graph/traversal.js.map +1 -1
  181. package/lib/dist/index.d.ts +81 -1
  182. package/lib/dist/index.d.ts.map +1 -1
  183. package/lib/dist/index.js +460 -10
  184. package/lib/dist/index.js.map +1 -1
  185. package/lib/dist/installer/index.d.ts +42 -0
  186. package/lib/dist/installer/index.d.ts.map +1 -1
  187. package/lib/dist/installer/index.js +97 -2
  188. package/lib/dist/installer/index.js.map +1 -1
  189. package/lib/dist/mcp/daemon.d.ts +35 -3
  190. package/lib/dist/mcp/daemon.d.ts.map +1 -1
  191. package/lib/dist/mcp/daemon.js +101 -9
  192. package/lib/dist/mcp/daemon.js.map +1 -1
  193. package/lib/dist/mcp/dynamic-boundaries.d.ts.map +1 -1
  194. package/lib/dist/mcp/dynamic-boundaries.js +2 -1
  195. package/lib/dist/mcp/dynamic-boundaries.js.map +1 -1
  196. package/lib/dist/mcp/early-ppid.d.ts +26 -0
  197. package/lib/dist/mcp/early-ppid.d.ts.map +1 -0
  198. package/lib/dist/mcp/early-ppid.js +29 -0
  199. package/lib/dist/mcp/early-ppid.js.map +1 -0
  200. package/lib/dist/mcp/index.d.ts.map +1 -1
  201. package/lib/dist/mcp/index.js +29 -4
  202. package/lib/dist/mcp/index.js.map +1 -1
  203. package/lib/dist/mcp/liveness-watchdog.d.ts +18 -1
  204. package/lib/dist/mcp/liveness-watchdog.d.ts.map +1 -1
  205. package/lib/dist/mcp/liveness-watchdog.js +73 -13
  206. package/lib/dist/mcp/liveness-watchdog.js.map +1 -1
  207. package/lib/dist/mcp/proxy.d.ts.map +1 -1
  208. package/lib/dist/mcp/proxy.js +30 -4
  209. package/lib/dist/mcp/proxy.js.map +1 -1
  210. package/lib/dist/mcp/query-pool.d.ts +14 -0
  211. package/lib/dist/mcp/query-pool.d.ts.map +1 -1
  212. package/lib/dist/mcp/query-pool.js +18 -0
  213. package/lib/dist/mcp/query-pool.js.map +1 -1
  214. package/lib/dist/mcp/session.d.ts +14 -0
  215. package/lib/dist/mcp/session.d.ts.map +1 -1
  216. package/lib/dist/mcp/session.js +28 -1
  217. package/lib/dist/mcp/session.js.map +1 -1
  218. package/lib/dist/mcp/startup-handshake.d.ts +44 -0
  219. package/lib/dist/mcp/startup-handshake.d.ts.map +1 -0
  220. package/lib/dist/mcp/startup-handshake.js +73 -0
  221. package/lib/dist/mcp/startup-handshake.js.map +1 -0
  222. package/lib/dist/mcp/tools.d.ts +22 -0
  223. package/lib/dist/mcp/tools.d.ts.map +1 -1
  224. package/lib/dist/mcp/tools.js +289 -23
  225. package/lib/dist/mcp/tools.js.map +1 -1
  226. package/lib/dist/mcp/transport.d.ts.map +1 -1
  227. package/lib/dist/mcp/transport.js +18 -0
  228. package/lib/dist/mcp/transport.js.map +1 -1
  229. package/lib/dist/project-config.d.ts +44 -0
  230. package/lib/dist/project-config.d.ts.map +1 -1
  231. package/lib/dist/project-config.js +151 -2
  232. package/lib/dist/project-config.js.map +1 -1
  233. package/lib/dist/resolution/c-fnptr-synthesizer.d.ts +2 -1
  234. package/lib/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
  235. package/lib/dist/resolution/c-fnptr-synthesizer.js +170 -146
  236. package/lib/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
  237. package/lib/dist/resolution/callback-synthesizer.d.ts +1 -1
  238. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  239. package/lib/dist/resolution/callback-synthesizer.js +1109 -97
  240. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  241. package/lib/dist/resolution/cooperative-yield.d.ts +32 -0
  242. package/lib/dist/resolution/cooperative-yield.d.ts.map +1 -0
  243. package/lib/dist/resolution/cooperative-yield.js +42 -0
  244. package/lib/dist/resolution/cooperative-yield.js.map +1 -0
  245. package/lib/dist/resolution/frameworks/cics.d.ts +20 -0
  246. package/lib/dist/resolution/frameworks/cics.d.ts.map +1 -0
  247. package/lib/dist/resolution/frameworks/cics.js +90 -0
  248. package/lib/dist/resolution/frameworks/cics.js.map +1 -0
  249. package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
  250. package/lib/dist/resolution/frameworks/index.js +6 -0
  251. package/lib/dist/resolution/frameworks/index.js.map +1 -1
  252. package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
  253. package/lib/dist/resolution/frameworks/java.js +14 -6
  254. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  255. package/lib/dist/resolution/frameworks/terraform.d.ts +38 -0
  256. package/lib/dist/resolution/frameworks/terraform.d.ts.map +1 -0
  257. package/lib/dist/resolution/frameworks/terraform.js +277 -0
  258. package/lib/dist/resolution/frameworks/terraform.js.map +1 -0
  259. package/lib/dist/resolution/goframe-synthesizer.d.ts +2 -1
  260. package/lib/dist/resolution/goframe-synthesizer.d.ts.map +1 -1
  261. package/lib/dist/resolution/goframe-synthesizer.js +8 -3
  262. package/lib/dist/resolution/goframe-synthesizer.js.map +1 -1
  263. package/lib/dist/resolution/import-resolver.d.ts +7 -0
  264. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  265. package/lib/dist/resolution/import-resolver.js +129 -4
  266. package/lib/dist/resolution/import-resolver.js.map +1 -1
  267. package/lib/dist/resolution/index.d.ts +64 -2
  268. package/lib/dist/resolution/index.d.ts.map +1 -1
  269. package/lib/dist/resolution/index.js +476 -58
  270. package/lib/dist/resolution/index.js.map +1 -1
  271. package/lib/dist/resolution/name-matcher.d.ts +22 -3
  272. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  273. package/lib/dist/resolution/name-matcher.js +613 -39
  274. package/lib/dist/resolution/name-matcher.js.map +1 -1
  275. package/lib/dist/resolution/strip-comments.d.ts +1 -1
  276. package/lib/dist/resolution/strip-comments.d.ts.map +1 -1
  277. package/lib/dist/resolution/strip-comments.js +49 -0
  278. package/lib/dist/resolution/strip-comments.js.map +1 -1
  279. package/lib/dist/resolution/types.d.ts +29 -0
  280. package/lib/dist/resolution/types.d.ts.map +1 -1
  281. package/lib/dist/resolution/workspace-packages.d.ts +10 -0
  282. package/lib/dist/resolution/workspace-packages.d.ts.map +1 -1
  283. package/lib/dist/resolution/workspace-packages.js +142 -4
  284. package/lib/dist/resolution/workspace-packages.js.map +1 -1
  285. package/lib/dist/search/identifier-segments.d.ts +60 -0
  286. package/lib/dist/search/identifier-segments.d.ts.map +1 -0
  287. package/lib/dist/search/identifier-segments.js +176 -0
  288. package/lib/dist/search/identifier-segments.js.map +1 -0
  289. package/lib/dist/sync/git-hooks.d.ts.map +1 -1
  290. package/lib/dist/sync/git-hooks.js +2 -0
  291. package/lib/dist/sync/git-hooks.js.map +1 -1
  292. package/lib/dist/sync/watcher.d.ts +10 -5
  293. package/lib/dist/sync/watcher.d.ts.map +1 -1
  294. package/lib/dist/sync/watcher.js +51 -14
  295. package/lib/dist/sync/watcher.js.map +1 -1
  296. package/lib/dist/sync/worktree.d.ts +9 -0
  297. package/lib/dist/sync/worktree.d.ts.map +1 -1
  298. package/lib/dist/sync/worktree.js +45 -0
  299. package/lib/dist/sync/worktree.js.map +1 -1
  300. package/lib/dist/types.d.ts +25 -2
  301. package/lib/dist/types.d.ts.map +1 -1
  302. package/lib/dist/types.js +10 -0
  303. package/lib/dist/types.js.map +1 -1
  304. package/lib/dist/upgrade/index.d.ts +32 -0
  305. package/lib/dist/upgrade/index.d.ts.map +1 -1
  306. package/lib/dist/upgrade/index.js +163 -14
  307. package/lib/dist/upgrade/index.js.map +1 -1
  308. package/lib/dist/upgrade/remove-binary.d.ts +87 -0
  309. package/lib/dist/upgrade/remove-binary.d.ts.map +1 -0
  310. package/lib/dist/upgrade/remove-binary.js +289 -0
  311. package/lib/dist/upgrade/remove-binary.js.map +1 -0
  312. package/lib/dist/upgrade/update-check.d.ts +92 -0
  313. package/lib/dist/upgrade/update-check.d.ts.map +1 -0
  314. package/lib/dist/upgrade/update-check.js +258 -0
  315. package/lib/dist/upgrade/update-check.js.map +1 -0
  316. package/lib/node_modules/.modules.yaml +1 -1
  317. package/lib/node_modules/.pnpm-workspace-state-v1.json +1 -1
  318. package/lib/package.json +1 -1
  319. package/package.json +1 -1
  320. package/lib/dist/reasoning/config.d.ts +0 -45
  321. package/lib/dist/reasoning/config.d.ts.map +0 -1
  322. package/lib/dist/reasoning/config.js +0 -171
  323. package/lib/dist/reasoning/config.js.map +0 -1
  324. package/lib/dist/reasoning/credentials.d.ts +0 -5
  325. package/lib/dist/reasoning/credentials.d.ts.map +0 -1
  326. package/lib/dist/reasoning/credentials.js +0 -83
  327. package/lib/dist/reasoning/credentials.js.map +0 -1
  328. package/lib/dist/reasoning/login.d.ts +0 -21
  329. package/lib/dist/reasoning/login.d.ts.map +0 -1
  330. package/lib/dist/reasoning/login.js +0 -85
  331. package/lib/dist/reasoning/login.js.map +0 -1
  332. package/lib/dist/reasoning/reasoner.d.ts +0 -43
  333. package/lib/dist/reasoning/reasoner.d.ts.map +0 -1
  334. package/lib/dist/reasoning/reasoner.js +0 -308
  335. package/lib/dist/reasoning/reasoner.js.map +0 -1
@@ -46,6 +46,7 @@ const tree_sitter_helpers_1 = require("./tree-sitter-helpers");
46
46
  const function_ref_1 = require("./function-ref");
47
47
  const generated_detection_1 = require("./generated-detection");
48
48
  const languages_1 = require("./languages");
49
+ const c_cpp_1 = require("./languages/c-cpp");
49
50
  const liquid_extractor_1 = require("./liquid-extractor");
50
51
  const razor_extractor_1 = require("./razor-extractor");
51
52
  const svelte_extractor_1 = require("./svelte-extractor");
@@ -56,6 +57,7 @@ const mybatis_extractor_1 = require("./mybatis-extractor");
56
57
  const vba_extractor_1 = require("./vba-extractor");
57
58
  const vba_form_extractor_1 = require("./vba-form-extractor");
58
59
  const sql_query_extractor_1 = require("./sql-query-extractor");
60
+ const cfml_extractor_1 = require("./cfml-extractor");
59
61
  const frameworks_1 = require("../resolution/frameworks");
60
62
  // Re-export for backward compatibility
61
63
  var tree_sitter_helpers_2 = require("./tree-sitter-helpers");
@@ -79,24 +81,68 @@ const VUE_STORE_FACTORY_CALLEES = new Set(['defineStore', 'createStore']);
79
81
  /** Distinct signals that a file is a Vuex/Pinia store (≥2 ⇒ treat a bare
80
82
  * `const actions = {…}` as a store collection — see looksLikeVueStoreFile). */
81
83
  const VUE_STORE_FILE_SIGNAL = /\bdefineStore\b|\bcreateStore\b|\bVuex\b|\bmutations\b|\bactions\b|\bgetters\b|\bnamespaced\b/g;
84
+ /**
85
+ * Erlang calls that take their real callee as (Module, Function, Args)
86
+ * ARGUMENTS — the spawn/apply family. Keys are the callee as the call site
87
+ * spells it: bare for auto-imported BIFs, `module:function` for remote calls.
88
+ * Used by the erlang branch of extractCall to lift a static MFA pair into a
89
+ * call edge (the spawned/applied function is otherwise invisible to the graph).
90
+ */
91
+ /** Compiler-predefined Erlang macros — no `-define` exists to link a use to. */
92
+ const ERLANG_PREDEFINED_MACROS = new Set([
93
+ 'MODULE', 'MODULE_STRING', 'FILE', 'LINE', 'MACHINE',
94
+ 'FUNCTION_NAME', 'FUNCTION_ARITY', 'OTP_RELEASE',
95
+ 'FEATURE_AVAILABLE', 'FEATURE_ENABLED',
96
+ ]);
97
+ const ERLANG_MFA_CALLS = new Set([
98
+ 'spawn', 'spawn_link', 'spawn_monitor', 'spawn_opt', 'apply',
99
+ 'erlang:spawn', 'erlang:spawn_link', 'erlang:spawn_monitor', 'erlang:spawn_opt', 'erlang:apply',
100
+ 'proc_lib:spawn', 'proc_lib:spawn_link', 'proc_lib:spawn_opt', 'proc_lib:start', 'proc_lib:start_link',
101
+ 'timer:apply_after', 'timer:apply_interval',
102
+ 'rpc:call', 'rpc:cast', 'rpc:async_call',
103
+ 'erpc:call', 'erpc:cast',
104
+ ]);
82
105
  /**
83
106
  * Extract the name from a node based on language
84
107
  */
85
108
  function extractName(node, source, extractor) {
109
+ const name = extractNameRaw(node, source, extractor);
110
+ // Universal fallback: recover a real identifier from a name still mangled by a
111
+ // macro the pre-parse didn't blank (C/C++ only — see recoverMangledName). A
112
+ // no-op on well-formed names, so a clean name is never altered.
113
+ return extractor.recoverMangledName ? extractor.recoverMangledName(name) : name;
114
+ }
115
+ function extractNameRaw(node, source, extractor) {
86
116
  const hookName = extractor.resolveName?.(node, source);
87
117
  if (hookName)
88
118
  return hookName;
89
119
  // Try field name first
90
120
  const nameNode = (0, tree_sitter_helpers_1.getChildByField)(node, extractor.nameField);
91
121
  if (nameNode) {
92
- // Unwrap pointer_declarator(s) for C/C++ pointer return types
122
+ // Unwrap pointer_declarator / reference_declarator for C/C++ pointer and
123
+ // reference return types (`int* f()`, `int& f()`, `int&& f()`). Without
124
+ // unwrapping the reference wrapper an inline reference-returning method is
125
+ // named "& f() const" instead of "f" — common in Unreal Engine gameplay
126
+ // headers (`const FGameplayTagContainer& GetActiveTags() const`). Out-of-line
127
+ // defs (`T& C::f()`) already resolve via the qualified-name hook. A
128
+ // pointer_declarator exposes its inner through a `declarator` field; a
129
+ // reference_declarator has none, so it's reached via namedChild(0).
93
130
  let resolved = nameNode;
94
- while (resolved.type === 'pointer_declarator') {
131
+ while (resolved.type === 'pointer_declarator' || resolved.type === 'reference_declarator') {
95
132
  const inner = (0, tree_sitter_helpers_1.getChildByField)(resolved, 'declarator') || resolved.namedChild(0);
96
133
  if (!inner)
97
134
  break;
98
135
  resolved = inner;
99
136
  }
137
+ // C++ user-defined conversion operator: the declarator is an `operator_cast`
138
+ // whose first child is the target type and second is the `() const` tail. Name
139
+ // it `operator <type>` (the conventional spelling) rather than the whole
140
+ // `operator EALSMovementState() const` declarator, so it matches symbolic
141
+ // overloads (`operator+`) and is findable by the type name.
142
+ if (resolved.type === 'operator_cast') {
143
+ const typeNode = resolved.namedChild(0);
144
+ return typeNode ? `operator ${(0, tree_sitter_helpers_1.getNodeText)(typeNode, source).trim()}` : (0, tree_sitter_helpers_1.getNodeText)(resolved, source);
145
+ }
100
146
  // Handle complex declarators (C/C++)
101
147
  if (resolved.type === 'function_declarator' || resolved.type === 'declarator') {
102
148
  const innerName = (0, tree_sitter_helpers_1.getChildByField)(resolved, 'declarator') || resolved.namedChild(0);
@@ -326,7 +372,7 @@ class TreeSitterExtractor {
326
372
  // Value-reference edges (default ON; set CODEGRAPH_VALUE_REFS=0 to disable; see flushValueRefs).
327
373
  // Same-file reads of file-scope const/var symbols → `references` edges so impact analysis catches
328
374
  // value consumers ("change this constant/table, affect its readers").
329
- static VALUE_REF_LANGS = new Set(['typescript', 'javascript', 'tsx', 'go', 'python', 'rust', 'ruby', 'c', 'java', 'csharp', 'php', 'scala', 'kotlin', 'swift', 'dart', 'pascal']);
375
+ static VALUE_REF_LANGS = new Set(['typescript', 'javascript', 'tsx', 'arkts', 'go', 'python', 'rust', 'ruby', 'c', 'java', 'csharp', 'php', 'scala', 'kotlin', 'swift', 'dart', 'pascal']);
330
376
  static MAX_VALUE_REF_NODES = 20_000;
331
377
  valueRefsEnabled = process.env.CODEGRAPH_VALUE_REFS !== '0';
332
378
  fileScopeValues = new Map();
@@ -335,6 +381,20 @@ class TreeSitterExtractor {
335
381
  errors = [];
336
382
  extractor = null;
337
383
  nodeStack = []; // Stack of parent node IDs
384
+ // C/C++ enclosing `namespace ns { … }` names, prepended to every contained
385
+ // symbol's qualifiedName (see visitNode). Prefix-only by design — no
386
+ // namespace NODE is created: `namespace cutlass {` opens in thousands of
387
+ // files, and a node per block would flood search with same-named symbols
388
+ // (the #1093 crowd-out failure mode). Always empty outside C/C++.
389
+ namespacePrefix = [];
390
+ // C++ local function-pointer bindings, per enclosing symbol:
391
+ // `auto kernel = &flash_fwd_kernel<…>;` recorded as callerId → kernel →
392
+ // {flash_fwd_kernel}, so a later `kernel<<<grid, block>>>(params)` (or plain
393
+ // `kernel(args)`) in the same body emits calls refs to the real target(s)
394
+ // instead of an unresolvable local name. Branch reassignments accumulate —
395
+ // each assigned target is a genuine possible callee. Same-body locality is
396
+ // the precision guard (the #932 table-dispatch philosophy scoped to locals).
397
+ cppLocalFnPtrs = new Map();
338
398
  methodIndex = null; // lookup key → node ID for Pascal defProc lookup
339
399
  // Function-as-value capture (#756): per-language spec + candidates collected
340
400
  // during the walk, gated & flushed into unresolvedReferences at end-of-file
@@ -395,7 +455,7 @@ class TreeSitterExtractor {
395
455
  // this.source so downstream getNodeText reads the same bytes the parser
396
456
  // saw (identical outside the blanked directive lines).
397
457
  if (this.extractor?.preParse) {
398
- this.source = this.extractor.preParse(this.source);
458
+ this.source = this.extractor.preParse(this.source, this.filePath);
399
459
  }
400
460
  this.tree = parser.parse(this.source) ?? null;
401
461
  if (!this.tree) {
@@ -853,6 +913,31 @@ class TreeSitterExtractor {
853
913
  if (skipChildren)
854
914
  return;
855
915
  }
916
+ // C++ namespace blocks: carry the namespace name as a qualifiedName prefix
917
+ // while walking the body, so `namespace flash { void compute_attn(); }`
918
+ // indexes compute_attn with qualifiedName `flash::compute_attn` and a
919
+ // namespace-qualified call (`flash::compute_attn(...)`) resolves by exact
920
+ // qualified match instead of never resolving — C++ namespaces previously
921
+ // left no trace in qualifiedNames at all, so every `ns::fn()` call site
922
+ // was a permanently dead edge (surfaced by #387 flow validation on
923
+ // flash-attention/cutlass, whose kernel dispatch is namespace-qualified).
924
+ // C++17 nested forms (`namespace a::b {`) prefix as written. An anonymous
925
+ // namespace falls through to the generic walk — its contents stay bare,
926
+ // matching how call sites spell them.
927
+ if (this.language === 'cpp' && nodeType === 'namespace_definition') {
928
+ const nameNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'name');
929
+ const nsName = nameNode ? (0, tree_sitter_helpers_1.getNodeText)(nameNode, this.source) : '';
930
+ if (nsName) {
931
+ this.namespacePrefix.push(nsName);
932
+ for (let i = 0; i < node.namedChildCount; i++) {
933
+ const child = node.namedChild(i);
934
+ if (child)
935
+ this.visitNode(child);
936
+ }
937
+ this.namespacePrefix.pop();
938
+ return;
939
+ }
940
+ }
856
941
  // Function-as-value capture (#756) — independent of the dispatch ladder
857
942
  // below (the captured container types have no other handler there), so it
858
943
  // can never shadow or be shadowed by an extraction branch.
@@ -1086,7 +1171,8 @@ class TreeSitterExtractor {
1086
1171
  // falls through to its normal declaration extraction).
1087
1172
  else if (nodeType === 'export_statement' &&
1088
1173
  (this.language === 'typescript' || this.language === 'tsx' ||
1089
- this.language === 'javascript' || this.language === 'jsx') &&
1174
+ this.language === 'javascript' || this.language === 'jsx' ||
1175
+ this.language === 'arkts') &&
1090
1176
  (0, tree_sitter_helpers_1.getChildByField)(node, 'source')) {
1091
1177
  const parentId = this.nodeStack[this.nodeStack.length - 1];
1092
1178
  if (parentId)
@@ -1116,7 +1202,7 @@ class TreeSitterExtractor {
1116
1202
  // produce an `instantiates` reference. Children still walked so
1117
1203
  // nested calls inside the constructor args (`new Foo(bar())`) get
1118
1204
  // their own `calls` refs.
1119
- else if (INSTANTIATION_KINDS.has(nodeType)) {
1205
+ else if (INSTANTIATION_KINDS.has(nodeType) || this.isVbnetConstructorShapedArrayCreation(node)) {
1120
1206
  this.extractInstantiation(node);
1121
1207
  // Java/C# `new T(...) { ... }` — anonymous class with body. Without
1122
1208
  // extracting it as a class node + its methods, the interface→impl
@@ -1267,7 +1353,8 @@ class TreeSitterExtractor {
1267
1353
  buildQualifiedName(name) {
1268
1354
  // Build a qualified name from the semantic hierarchy only (no file path).
1269
1355
  // The file path is stored separately in filePath and pollutes FTS if included here.
1270
- const parts = [];
1356
+ // C/C++ enclosing namespaces prefix first (empty for every other language).
1357
+ const parts = [...this.namespacePrefix];
1271
1358
  for (const nodeId of this.nodeStack) {
1272
1359
  const node = this.nodes.find((n) => n.id === nodeId);
1273
1360
  if (node && node.kind !== 'file') {
@@ -1486,6 +1573,15 @@ class TreeSitterExtractor {
1486
1573
  extractClass(node, kind = 'class') {
1487
1574
  if (!this.extractor)
1488
1575
  return;
1576
+ // Skip forward declarations / elaborated type references (`class Foo;`) in
1577
+ // languages that opt in — bodiless there means "not a definition", so it
1578
+ // would otherwise mint a phantom node competing with the real definition
1579
+ // (#1093). Languages where a bodiless class is complete (Kotlin, Scala)
1580
+ // leave the flag unset. Resolved once here and reused for the body walk.
1581
+ const resolvedBody = this.extractor.resolveBody?.(node, this.extractor.bodyField)
1582
+ ?? (0, tree_sitter_helpers_1.getChildByField)(node, this.extractor.bodyField);
1583
+ if (this.extractor.skipBodilessClass && !resolvedBody)
1584
+ return;
1489
1585
  const name = extractName(node, this.source, this.extractor);
1490
1586
  const docstring = (0, tree_sitter_helpers_1.getPrecedingDocstring)(node, this.source);
1491
1587
  const visibility = this.extractor.getVisibility?.(node);
@@ -1505,10 +1601,7 @@ class TreeSitterExtractor {
1505
1601
  this.extractDecoratorsFor(node, classNode.id);
1506
1602
  // Push to stack and visit body
1507
1603
  this.nodeStack.push(classNode.id);
1508
- let body = this.extractor.resolveBody?.(node, this.extractor.bodyField)
1509
- ?? (0, tree_sitter_helpers_1.getChildByField)(node, this.extractor.bodyField);
1510
- if (!body)
1511
- body = node;
1604
+ const body = resolvedBody ?? node;
1512
1605
  // Visit all children for methods and properties
1513
1606
  for (let i = 0; i < body.namedChildCount; i++) {
1514
1607
  const child = body.namedChild(i);
@@ -2342,7 +2435,8 @@ class TreeSitterExtractor {
2342
2435
  const isExported = this.extractor.isExported?.(node, this.source) ?? false;
2343
2436
  // Extract variable declarators based on language
2344
2437
  if (this.language === 'typescript' || this.language === 'javascript' ||
2345
- this.language === 'tsx' || this.language === 'jsx') {
2438
+ this.language === 'tsx' || this.language === 'jsx' || this.language === 'cfscript' ||
2439
+ this.language === 'arkts') {
2346
2440
  // Handle lexical_declaration and variable_declaration
2347
2441
  // These contain one or more variable_declarator children
2348
2442
  for (let i = 0; i < node.namedChildCount; i++) {
@@ -2756,7 +2850,7 @@ class TreeSitterExtractor {
2756
2850
  // property/method nodes under the type alias so `recorder.stop()`
2757
2851
  // can attach the call edge to `RecorderHandle.stop` instead of
2758
2852
  // an unrelated class method picked by path-proximity (#359).
2759
- if (this.language === 'typescript' || this.language === 'tsx') {
2853
+ if (this.language === 'typescript' || this.language === 'tsx' || this.language === 'arkts') {
2760
2854
  this.extractTsTypeAliasMembers(value, typeAliasNode);
2761
2855
  // `type List = [ Service<'name', Req, Resp>, … ]` — surface each
2762
2856
  // entry's string-literal name as a searchable member (issue #634).
@@ -2977,7 +3071,8 @@ class TreeSitterExtractor {
2977
3071
  // Link each imported binding to its definition so imported-but-not-
2978
3072
  // called/typed symbols still record a cross-file dependency (TS/JS only).
2979
3073
  if (this.language === 'typescript' || this.language === 'tsx' ||
2980
- this.language === 'javascript' || this.language === 'jsx') {
3074
+ this.language === 'javascript' || this.language === 'jsx' ||
3075
+ this.language === 'arkts') {
2981
3076
  const parentId = this.nodeStack[this.nodeStack.length - 1];
2982
3077
  if (parentId)
2983
3078
  this.emitImportBindingRefs(node, parentId);
@@ -3416,12 +3511,522 @@ class TreeSitterExtractor {
3416
3511
  /**
3417
3512
  * Extract a function call
3418
3513
  */
3514
+ /**
3515
+ * The module an Erlang gen_server target expression statically names, or
3516
+ * null when it's dynamic (pid/var/tuple form). Static shapes:
3517
+ * - a bare atom — either this module or another one; OTP's dominant
3518
+ * registration convention (`{local, ?MODULE}`) names a server process
3519
+ * after its module, so `gen_server:call(other_mod, …)` reaches
3520
+ * `other_mod`'s handlers. A registered name that matches no module
3521
+ * resolves to nothing downstream (the qualified ref just drops).
3522
+ * - `?MODULE`, or a macro the file defines as `?MODULE`
3523
+ * (`-define(SERVER, ?MODULE)` — the standard self idiom)
3524
+ * - a macro the file defines as a bare atom
3525
+ * (`-define(STORE, kv_store)` — the cross-module variant)
3526
+ * The macro tables are memoized per file (single entry — extraction is
3527
+ * file-sequential).
3528
+ */
3529
+ erlangServerMacroFile = '';
3530
+ erlangSelfMacros = new Set();
3531
+ erlangAtomMacros = new Map();
3532
+ resolveErlangGenServerTarget(target) {
3533
+ const ownModule = (this.filePath.split('/').pop() ?? '').replace(/\.erl$/, '');
3534
+ if (target.type === 'atom') {
3535
+ const name = (0, tree_sitter_helpers_1.getNodeText)(target, this.source).replace(/^'([\s\S]*)'$/, '$1');
3536
+ return name || null;
3537
+ }
3538
+ if (target.type !== 'macro_call_expr')
3539
+ return null;
3540
+ const nameNode = (0, tree_sitter_helpers_1.getChildByField)(target, 'name');
3541
+ if (!nameNode)
3542
+ return null;
3543
+ const macroName = (0, tree_sitter_helpers_1.getNodeText)(nameNode, this.source);
3544
+ if (macroName === 'MODULE')
3545
+ return ownModule || null;
3546
+ if (this.erlangServerMacroFile !== this.filePath) {
3547
+ this.erlangServerMacroFile = this.filePath;
3548
+ this.erlangSelfMacros = new Set();
3549
+ this.erlangAtomMacros = new Map();
3550
+ let root = target;
3551
+ while (root.parent)
3552
+ root = root.parent;
3553
+ for (let i = 0; i < root.namedChildCount; i++) {
3554
+ const form = root.namedChild(i);
3555
+ if (form?.type !== 'pp_define')
3556
+ continue;
3557
+ const lhs = (0, tree_sitter_helpers_1.getChildByField)(form, 'lhs');
3558
+ const defName = lhs ? (0, tree_sitter_helpers_1.getChildByField)(lhs, 'name') : null;
3559
+ const replacement = (0, tree_sitter_helpers_1.getChildByField)(form, 'replacement');
3560
+ if (!defName || !replacement)
3561
+ continue;
3562
+ if (replacement.type === 'macro_call_expr' &&
3563
+ (0, tree_sitter_helpers_1.getChildByField)(replacement, 'name') &&
3564
+ (0, tree_sitter_helpers_1.getNodeText)((0, tree_sitter_helpers_1.getChildByField)(replacement, 'name'), this.source) === 'MODULE') {
3565
+ this.erlangSelfMacros.add((0, tree_sitter_helpers_1.getNodeText)(defName, this.source));
3566
+ }
3567
+ else if (replacement.type === 'atom') {
3568
+ this.erlangAtomMacros.set((0, tree_sitter_helpers_1.getNodeText)(defName, this.source), (0, tree_sitter_helpers_1.getNodeText)(replacement, this.source).replace(/^'([\s\S]*)'$/, '$1'));
3569
+ }
3570
+ }
3571
+ }
3572
+ if (this.erlangSelfMacros.has(macroName))
3573
+ return ownModule || null;
3574
+ return this.erlangAtomMacros.get(macroName) ?? null;
3575
+ }
3419
3576
  extractCall(node) {
3420
3577
  if (this.nodeStack.length === 0)
3421
3578
  return;
3422
3579
  const callerId = this.nodeStack[this.nodeStack.length - 1];
3423
3580
  if (!callerId)
3424
3581
  return;
3582
+ // VB.NET: `foo(args)` is syntactically ambiguous between a call and an
3583
+ // index read, so the grammar parses non-empty parens as
3584
+ // array_access_expression (field `array`, not `function`) — even Roslyn
3585
+ // parses both as InvocationExpression and resolves during binding. Treat
3586
+ // all three shapes as call sites: the callee is the member/identifier
3587
+ // under the array/function field, qualified with a simple-identifier
3588
+ // receiver for resolution. Index reads on collections simply never
3589
+ // resolve to a callable, so they cost nothing.
3590
+ if (this.language === 'vbnet' &&
3591
+ (node.type === 'array_access_expression' ||
3592
+ node.type === 'invocation_expression' ||
3593
+ node.type === 'generic_invocation_expression')) {
3594
+ const fn = (0, tree_sitter_helpers_1.getChildByField)(node, 'function') || (0, tree_sitter_helpers_1.getChildByField)(node, 'array');
3595
+ if (!fn)
3596
+ return;
3597
+ let calleeName = '';
3598
+ if (fn.type === 'member_access_expression') {
3599
+ const member = (0, tree_sitter_helpers_1.getChildByField)(fn, 'member');
3600
+ const memberName = member ? (0, tree_sitter_helpers_1.getNodeText)(member, this.source) : '';
3601
+ if (!memberName)
3602
+ return;
3603
+ const receiver = (0, tree_sitter_helpers_1.getChildByField)(fn, 'object');
3604
+ const SKIP = new Set(['me', 'mybase', 'myclass']);
3605
+ if (receiver && receiver.type === 'identifier' && !SKIP.has((0, tree_sitter_helpers_1.getNodeText)(receiver, this.source).toLowerCase())) {
3606
+ calleeName = `${(0, tree_sitter_helpers_1.getNodeText)(receiver, this.source)}.${memberName}`;
3607
+ }
3608
+ else {
3609
+ calleeName = memberName;
3610
+ }
3611
+ }
3612
+ else if (fn.type === 'identifier') {
3613
+ calleeName = (0, tree_sitter_helpers_1.getNodeText)(fn, this.source);
3614
+ }
3615
+ else {
3616
+ return; // parenthesized/chained receivers: no static name to link
3617
+ }
3618
+ if (calleeName) {
3619
+ this.unresolvedReferences.push({
3620
+ fromNodeId: callerId,
3621
+ referenceName: calleeName,
3622
+ referenceKind: 'calls',
3623
+ line: node.startPosition.row + 1,
3624
+ column: node.startPosition.column,
3625
+ });
3626
+ }
3627
+ return;
3628
+ }
3629
+ // Erlang: a local call is `call(expr: atom, args)`; a remote call nests it
3630
+ // under `remote(module: remote_module, fun: call)` — the module qualifier
3631
+ // lives on the PARENT. Remote calls are emitted as `mod::fn`, which is
3632
+ // byte-identical to the qualifiedName the module namespace gives every
3633
+ // function (see packageTypes in languages/erlang.ts), so they resolve via
3634
+ // matchByQualifiedName. A var/macro callee or module (`F(X)`, `?M(X)`,
3635
+ // `Mod:handle(X)`) has no static target — except `?MODULE:fn(X)`, which the
3636
+ // bare name + same-file preference resolves correctly. `fun name/1` /
3637
+ // `fun mod:name/1` values are function REFERENCES (callback registration),
3638
+ // and record construction/update/index/field-access are `references` to the
3639
+ // record's struct node.
3640
+ if (this.language === 'erlang') {
3641
+ const line = node.startPosition.row + 1;
3642
+ const column = node.startPosition.column;
3643
+ const erlAtom = (n) => (0, tree_sitter_helpers_1.getNodeText)(n, this.source).replace(/^'([\s\S]*)'$/, '$1');
3644
+ if (node.type === 'call') {
3645
+ let callee = (0, tree_sitter_helpers_1.getChildByField)(node, 'expr');
3646
+ let moduleNode = null;
3647
+ // remote(module, fun: call) — the shape the grammar produces today; the
3648
+ // node-types also permit call(expr: remote), so handle both nestings.
3649
+ if (node.parent?.type === 'remote') {
3650
+ moduleNode = (0, tree_sitter_helpers_1.getChildByField)(node.parent, 'module');
3651
+ }
3652
+ else if (callee?.type === 'remote') {
3653
+ moduleNode = (0, tree_sitter_helpers_1.getChildByField)(callee, 'module');
3654
+ callee = (0, tree_sitter_helpers_1.getChildByField)(callee, 'fun');
3655
+ }
3656
+ if (callee?.type === 'atom') {
3657
+ const fnBare = erlAtom(callee);
3658
+ let calleeName = fnBare;
3659
+ const moduleExpr = moduleNode ? (0, tree_sitter_helpers_1.getChildByField)(moduleNode, 'module') : null;
3660
+ if (moduleExpr?.type === 'atom') {
3661
+ calleeName = `${erlAtom(moduleExpr)}::${calleeName}`;
3662
+ }
3663
+ else if (moduleExpr) {
3664
+ // Non-atom module qualifier. `?MODULE:f(X)` targets THIS module —
3665
+ // keep the bare name so same-file preference resolves it. Anything
3666
+ // else (`Mod:f(X)`) is behaviour-style dynamic dispatch with no
3667
+ // static target: emitting the bare name would link an arbitrary
3668
+ // same-named function, so stay silent instead.
3669
+ const macroName = moduleExpr.type === 'macro_call_expr' ? (0, tree_sitter_helpers_1.getChildByField)(moduleExpr, 'name') : null;
3670
+ if (!macroName || (0, tree_sitter_helpers_1.getNodeText)(macroName, this.source) !== 'MODULE')
3671
+ return;
3672
+ }
3673
+ this.unresolvedReferences.push({
3674
+ fromNodeId: callerId,
3675
+ referenceName: calleeName,
3676
+ referenceKind: 'calls',
3677
+ line,
3678
+ column,
3679
+ });
3680
+ // gen_server dispatch: `gen_server:call(?SERVER, Msg)` /
3681
+ // `gen_server:cast(other_mod, Msg)` — a request routes to the TARGET
3682
+ // module's handle_call/handle_cast. The target is static when the
3683
+ // first argument names a module: ?MODULE or a ?MODULE-defined macro
3684
+ // (the self API-wrapper idiom), a bare atom (OTP's `{local, ?MODULE}`
3685
+ // convention names a server after its module, so a cross-module
3686
+ // registered name reaches that module's handlers — and a registered
3687
+ // name matching no module resolves to nothing), or a macro defined
3688
+ // as a bare atom. Pid/var/tuple targets stay silent.
3689
+ if (moduleExpr?.type === 'atom' &&
3690
+ erlAtom(moduleExpr) === 'gen_server' &&
3691
+ (fnBare === 'call' || fnBare === 'cast' || fnBare === 'send_request')) {
3692
+ const argsNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'args');
3693
+ const target = argsNode?.namedChild(0) ?? null;
3694
+ const targetModule = target ? this.resolveErlangGenServerTarget(target) : null;
3695
+ if (targetModule) {
3696
+ this.unresolvedReferences.push({
3697
+ fromNodeId: callerId,
3698
+ referenceName: `${targetModule}::${fnBare === 'cast' ? 'handle_cast' : 'handle_call'}`,
3699
+ referenceKind: 'calls',
3700
+ line,
3701
+ column,
3702
+ });
3703
+ }
3704
+ }
3705
+ // MFA-in-argument dispatch: the spawn/apply family names its real
3706
+ // callee in ARGUMENT position — `proc_lib:spawn_link(?MODULE,
3707
+ // request_process, [Req, Env, Middlewares])` — so the walker above
3708
+ // sees only the spawn itself and the spawned function ends up with
3709
+ // zero callers (measured on cowboy: request_process had no incoming
3710
+ // edges and the agent Read the file to find it). When the (Module,
3711
+ // Function) pair is static, lift it as a call edge. The pair is
3712
+ // found positionally-agnostically (first adjacent module-atom/
3713
+ // ?MODULE + atom pair) so every arity variant works: spawn/3,
3714
+ // spawn(Node,M,F,A)/4, timer:apply_after(Time,M,F,A),
3715
+ // rpc:call(Node,M,F,A). A var module or fun stays silent.
3716
+ const familyKey = moduleExpr?.type === 'atom' ? `${erlAtom(moduleExpr)}:${fnBare}` : fnBare;
3717
+ if (ERLANG_MFA_CALLS.has(familyKey)) {
3718
+ const argsNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'args');
3719
+ const argExprs = argsNode ? argsNode.namedChildren : [];
3720
+ for (let i = 0; i + 1 < argExprs.length; i++) {
3721
+ const m = argExprs[i];
3722
+ const f = argExprs[i + 1];
3723
+ if (f.type !== 'atom')
3724
+ continue;
3725
+ const isLocalModule = m.type === 'macro_call_expr' &&
3726
+ (0, tree_sitter_helpers_1.getChildByField)(m, 'name') !== null &&
3727
+ (0, tree_sitter_helpers_1.getNodeText)((0, tree_sitter_helpers_1.getChildByField)(m, 'name'), this.source) === 'MODULE';
3728
+ if (m.type !== 'atom' && !isLocalModule)
3729
+ continue;
3730
+ this.unresolvedReferences.push({
3731
+ fromNodeId: callerId,
3732
+ referenceName: isLocalModule ? erlAtom(f) : `${erlAtom(m)}::${erlAtom(f)}`,
3733
+ referenceKind: 'calls',
3734
+ line: f.startPosition.row + 1,
3735
+ column: f.startPosition.column,
3736
+ });
3737
+ break;
3738
+ }
3739
+ }
3740
+ }
3741
+ return;
3742
+ }
3743
+ if (node.type === 'internal_fun' || node.type === 'external_fun') {
3744
+ const funNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'fun');
3745
+ if (funNode?.type !== 'atom')
3746
+ return; // fun Mod:F/A with var parts — dynamic
3747
+ let refName = erlAtom(funNode);
3748
+ if (node.type === 'external_fun') {
3749
+ const moduleWrapper = (0, tree_sitter_helpers_1.getChildByField)(node, 'module');
3750
+ const moduleAtom = moduleWrapper ? (0, tree_sitter_helpers_1.getChildByField)(moduleWrapper, 'name') : null;
3751
+ if (moduleAtom?.type !== 'atom')
3752
+ return;
3753
+ refName = `${erlAtom(moduleAtom)}::${refName}`;
3754
+ }
3755
+ this.unresolvedReferences.push({
3756
+ fromNodeId: callerId,
3757
+ referenceName: refName,
3758
+ referenceKind: 'references',
3759
+ line,
3760
+ column,
3761
+ });
3762
+ return;
3763
+ }
3764
+ if (node.type === 'macro_call_expr') {
3765
+ // Macro use site → the `-define` constant node. Function-like uses
3766
+ // (`?LOG_AUDIT(X)` — args present) are inlined code, so they join the
3767
+ // call chain and connect through the macro node to the body's calls
3768
+ // (attributed there by handlePpDefine); bare reads (`?TIMEOUT`) are
3769
+ // `references`, answering "where is this macro used" without
3770
+ // polluting call paths. Compiler-predefined macros carry no
3771
+ // definition to link. The use site's ARGUMENTS are children and keep
3772
+ // walking, so a call nested in `?assertEqual(ok, do_thing())` still
3773
+ // attributes to the enclosing function.
3774
+ const macroName = (0, tree_sitter_helpers_1.getChildByField)(node, 'name');
3775
+ if (!macroName)
3776
+ return;
3777
+ const name = (0, tree_sitter_helpers_1.getNodeText)(macroName, this.source);
3778
+ if (ERLANG_PREDEFINED_MACROS.has(name))
3779
+ return;
3780
+ this.unresolvedReferences.push({
3781
+ fromNodeId: callerId,
3782
+ referenceName: name,
3783
+ referenceKind: (0, tree_sitter_helpers_1.getChildByField)(node, 'args') ? 'calls' : 'references',
3784
+ line,
3785
+ column,
3786
+ });
3787
+ return;
3788
+ }
3789
+ // record_expr / record_update_expr / record_index_expr / record_field_expr
3790
+ const recordName = (0, tree_sitter_helpers_1.getChildByField)(node, 'name');
3791
+ const recordAtom = recordName?.type === 'record_name' ? (0, tree_sitter_helpers_1.getChildByField)(recordName, 'name') : null;
3792
+ if (recordAtom?.type === 'atom') {
3793
+ this.unresolvedReferences.push({
3794
+ fromNodeId: callerId,
3795
+ referenceName: erlAtom(recordAtom),
3796
+ referenceKind: 'references',
3797
+ line,
3798
+ column,
3799
+ });
3800
+ }
3801
+ return;
3802
+ }
3803
+ // Ruby `call` nodes use `receiver` + `method` fields (tree-sitter-ruby), not
3804
+ // the `object`/`name`/`function` fields the branches below expect — so
3805
+ // without this they fell through to the generic path, which took the
3806
+ // receiver as the callee and DROPPED the method name: `lg.log()` produced a
3807
+ // `calls` ref to `lg` (unresolvable) and no method edge was ever recorded,
3808
+ // so a Ruby method's callers/impact were invisible (#1108 follow-up). Build
3809
+ // `receiver.method` so the resolver — and local-variable type inference —
3810
+ // can link it; `Foo.new` stays an instantiation.
3811
+ if (this.language === 'ruby' && (node.type === 'call' || node.type === 'method_call')) {
3812
+ const methodNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'method');
3813
+ const methodName = methodNode ? (0, tree_sitter_helpers_1.getNodeText)(methodNode, this.source) : '';
3814
+ if (!methodName)
3815
+ return; // operator/element-reference call with no method name
3816
+ const receiverNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'receiver');
3817
+ const line = node.startPosition.row + 1;
3818
+ const column = node.startPosition.column;
3819
+ if (!receiverNode) {
3820
+ // Bare `foo(...)` — just the method name (unchanged behavior).
3821
+ this.unresolvedReferences.push({ fromNodeId: callerId, referenceName: methodName, referenceKind: 'calls', line, column });
3822
+ return;
3823
+ }
3824
+ const receiverName = (0, tree_sitter_helpers_1.getNodeText)(receiverNode, this.source);
3825
+ // `Foo.new` / `Foo::Bar.new` is construction — emit an `instantiates` ref to
3826
+ // the class (last `::` segment), preserving the "what creates X" edge.
3827
+ if (methodName === 'new') {
3828
+ const className = receiverName.includes('::')
3829
+ ? receiverName.slice(receiverName.lastIndexOf('::') + 2)
3830
+ : receiverName;
3831
+ if (/^[A-Z]/.test(className)) {
3832
+ this.unresolvedReferences.push({ fromNodeId: callerId, referenceName: className, referenceKind: 'instantiates', line, column });
3833
+ return;
3834
+ }
3835
+ }
3836
+ const SKIP_RECEIVERS = new Set(['self', 'super']);
3837
+ const skip = SKIP_RECEIVERS.has(receiverName);
3838
+ this.unresolvedReferences.push({
3839
+ fromNodeId: callerId,
3840
+ referenceName: skip ? methodName : `${receiverName}.${methodName}`,
3841
+ referenceKind: 'calls',
3842
+ line,
3843
+ column,
3844
+ });
3845
+ // A capitalized (constant) receiver — `Foo.bar`, a class/module method call
3846
+ // — is itself a dependency on that constant; emit a `references` ref so a
3847
+ // class used only via its class methods still records a dependent (the edge
3848
+ // the old receiver-only callee happened to provide, now made explicit).
3849
+ if (!skip && receiverNode.type === 'constant') {
3850
+ this.unresolvedReferences.push({
3851
+ fromNodeId: callerId,
3852
+ referenceName: receiverName,
3853
+ referenceKind: 'references',
3854
+ line: receiverNode.startPosition.row + 1,
3855
+ column: receiverNode.startPosition.column,
3856
+ });
3857
+ }
3858
+ return;
3859
+ }
3860
+ // ArkTS build()-DSL handling. Three shapes carry UI-attribute chains, and
3861
+ // all of their attribute names are emitted with a LEADING DOT
3862
+ // (`.titleStyle`, `.width`) — an impossible identifier that routes them to
3863
+ // a dedicated matcher strategy resolving ONLY to decorator-marked
3864
+ // attribute helpers (`@Extend`/`@Styles`/`@AnimatableExtend`/`@Builder`
3865
+ // functions). Bare names would go through global name matching, where
3866
+ // framework attributes (`.width`, `.fontSize`, appearing on nearly every
3867
+ // UI line) hit arbitrary same-named symbols — measured on the OpenHarmony
3868
+ // samples monorepo, that produced 36k wrong edges (17% of all calls),
3869
+ // including single properties with 3,400+ false callers.
3870
+ //
3871
+ // 1. `Column({space:8}) { … }.height('100%')` — ONE
3872
+ // arkui_component_expression: `function:` = the component, chained
3873
+ // attributes as repeated `property:`/`arguments:` field pairs.
3874
+ // The component ref (`Column`, `TodoRow`) stays a PLAIN name — it
3875
+ // resolves to the child `@Component struct`, giving the parent→child
3876
+ // component-tree edge the way JSX children do for React.
3877
+ // 2. `Image(x).width(10).onClick(this.f)` — ordinary nested
3878
+ // call_expressions whose `function:` is a member_expression chained
3879
+ // on a CALL RESULT (never a named receiver, so `svc.save()` /
3880
+ // `this.vm.load()` are untouched and fall through to the generic
3881
+ // paths below).
3882
+ // 3. A nested component whose chain starts on the line AFTER its
3883
+ // closing `}` inside arkui_children — the grammar detaches the chain
3884
+ // into sibling `leading_dot_expression(identifier)` +
3885
+ // `parenthesized_expression(args)` statement pairs; reassemble from
3886
+ // the siblings.
3887
+ //
3888
+ // `.onXxx(this.handler)` METHOD-REFERENCE bindings (no call parens, so
3889
+ // nothing else records them) additionally emit a call ref to the bare
3890
+ // handler name — same-class resolution links the tap→handler hop.
3891
+ // Arrow-function handlers need nothing: their bodies' calls already
3892
+ // attribute to the enclosing build(). Children/argument subtrees are
3893
+ // still walked by the caller, so nested components extract normally.
3894
+ if (this.language === 'arkts') {
3895
+ const emitAttr = (nameNode) => {
3896
+ const attrName = (0, tree_sitter_helpers_1.getNodeText)(nameNode, this.source);
3897
+ if (!attrName)
3898
+ return;
3899
+ this.unresolvedReferences.push({
3900
+ fromNodeId: callerId,
3901
+ referenceName: '.' + attrName,
3902
+ referenceKind: 'calls',
3903
+ line: nameNode.startPosition.row + 1,
3904
+ column: nameNode.startPosition.column,
3905
+ });
3906
+ };
3907
+ // Emit `handler` for each bare `this.handler` among an on-attribute's
3908
+ // arguments.
3909
+ const emitThisHandlers = (args) => {
3910
+ if (!args)
3911
+ return;
3912
+ for (let j = 0; j < args.namedChildCount; j++) {
3913
+ const arg = args.namedChild(j);
3914
+ if (arg?.type !== 'member_expression')
3915
+ continue;
3916
+ const obj = (0, tree_sitter_helpers_1.getChildByField)(arg, 'object');
3917
+ const prop = (0, tree_sitter_helpers_1.getChildByField)(arg, 'property');
3918
+ if (obj?.type === 'this' && prop) {
3919
+ this.unresolvedReferences.push({
3920
+ fromNodeId: callerId,
3921
+ referenceName: (0, tree_sitter_helpers_1.getNodeText)(prop, this.source),
3922
+ referenceKind: 'calls',
3923
+ line: arg.startPosition.row + 1,
3924
+ column: arg.startPosition.column,
3925
+ });
3926
+ }
3927
+ }
3928
+ };
3929
+ // Shape 1: arkui_component_expression with property/arguments pairs.
3930
+ if (node.type === 'arkui_component_expression') {
3931
+ const componentField = (0, tree_sitter_helpers_1.getChildByField)(node, 'function');
3932
+ if (componentField && componentField.type === 'identifier') {
3933
+ this.unresolvedReferences.push({
3934
+ fromNodeId: callerId,
3935
+ referenceName: (0, tree_sitter_helpers_1.getNodeText)(componentField, this.source),
3936
+ referenceKind: 'calls',
3937
+ line: node.startPosition.row + 1,
3938
+ column: node.startPosition.column,
3939
+ });
3940
+ }
3941
+ for (let i = 0; i < node.childCount; i++) {
3942
+ const child = node.child(i);
3943
+ if (!child || child.type !== 'property_identifier')
3944
+ continue;
3945
+ emitAttr(child);
3946
+ if (/^on[A-Z]/.test((0, tree_sitter_helpers_1.getNodeText)(child, this.source))) {
3947
+ // The attribute's arguments node is the next `arguments`-typed
3948
+ // child before the following attribute name.
3949
+ let args = null;
3950
+ for (let k = i + 1; k < node.childCount; k++) {
3951
+ const next = node.child(k);
3952
+ if (!next)
3953
+ continue;
3954
+ if (next.type === 'property_identifier')
3955
+ break;
3956
+ if (next.type === 'arguments') {
3957
+ args = next;
3958
+ break;
3959
+ }
3960
+ }
3961
+ emitThisHandlers(args);
3962
+ }
3963
+ }
3964
+ return;
3965
+ }
3966
+ // Shape 2: fluent chain on a call result —
3967
+ // call_expression(function: member_expression(object: <call>)), or the
3968
+ // grammar's DSL-specific arkui_dsl_decorator_member_expression (same
3969
+ // object/property fields; produced e.g. by `Column() { … }.alignItems(x)`
3970
+ // in some chain positions — it ONLY occurs in attribute chains).
3971
+ if (node.type === 'call_expression') {
3972
+ const fn = (0, tree_sitter_helpers_1.getChildByField)(node, 'function');
3973
+ if (fn?.type === 'member_expression' || fn?.type === 'arkui_dsl_decorator_member_expression') {
3974
+ const obj = (0, tree_sitter_helpers_1.getChildByField)(fn, 'object');
3975
+ const prop = (0, tree_sitter_helpers_1.getChildByField)(fn, 'property');
3976
+ if (prop &&
3977
+ (fn.type === 'arkui_dsl_decorator_member_expression' ||
3978
+ obj?.type === 'call_expression' ||
3979
+ obj?.type === 'arkui_component_expression')) {
3980
+ emitAttr(prop);
3981
+ if (/^on[A-Z]/.test((0, tree_sitter_helpers_1.getNodeText)(prop, this.source))) {
3982
+ emitThisHandlers((0, tree_sitter_helpers_1.getChildByField)(node, 'arguments'));
3983
+ }
3984
+ return;
3985
+ }
3986
+ }
3987
+ // The INNERMOST call of a proper-form detached chain
3988
+ // (`.alignItems(x).layoutWeight(1)…` under a leading_dot_expression)
3989
+ // has a BARE IDENTIFIER function — the leading dot was consumed by
3990
+ // the wrapper, so it masquerades as a plain `alignItems(...)` call.
3991
+ // Walk up the member/call alternation; topping out at
3992
+ // leading_dot_expression means the dot belongs to this chain.
3993
+ if (fn?.type === 'identifier') {
3994
+ let p = node.parent;
3995
+ while (p && (p.type === 'member_expression' || p.type === 'call_expression')) {
3996
+ p = p.parent;
3997
+ }
3998
+ if (p?.type === 'leading_dot_expression') {
3999
+ emitAttr(fn);
4000
+ if (/^on[A-Z]/.test((0, tree_sitter_helpers_1.getNodeText)(fn, this.source))) {
4001
+ emitThisHandlers((0, tree_sitter_helpers_1.getChildByField)(node, 'arguments'));
4002
+ }
4003
+ return;
4004
+ }
4005
+ }
4006
+ // Not a chained attribute — fall through to the generic call paths.
4007
+ }
4008
+ // Shape 3: detached chain segment — leading_dot_expression whose only
4009
+ // named child is a bare identifier; its arguments sit in the NEXT
4010
+ // sibling statement as a parenthesized_expression.
4011
+ if (node.type === 'leading_dot_expression') {
4012
+ const only = node.namedChildCount === 1 ? node.namedChild(0) : null;
4013
+ if (only && only.type === 'identifier') {
4014
+ emitAttr(only);
4015
+ if (/^on[A-Z]/.test((0, tree_sitter_helpers_1.getNodeText)(only, this.source))) {
4016
+ const stmt = node.parent; // expression_statement
4017
+ const nextStmt = stmt?.nextNamedSibling;
4018
+ const paren = nextStmt?.namedChild(0);
4019
+ if (paren?.type === 'parenthesized_expression') {
4020
+ emitThisHandlers(paren);
4021
+ }
4022
+ }
4023
+ }
4024
+ // The proper form (child is a call_expression chain, as inside
4025
+ // `@Extend` bodies) needs nothing here — the walker descends into it
4026
+ // and the inner call_expressions take the paths above.
4027
+ return;
4028
+ }
4029
+ }
3425
4030
  // Get the function/method being called
3426
4031
  let calleeName = '';
3427
4032
  // Java/Kotlin method_invocation has 'object' + 'name' fields instead of 'function'
@@ -3713,6 +4318,20 @@ class TreeSitterExtractor {
3713
4318
  }
3714
4319
  calleeName = reencode ? `${innerCallee}().${methodName}` : methodName;
3715
4320
  }
4321
+ else if (this.language === 'cfscript' &&
4322
+ receiver &&
4323
+ receiver.type === 'member_expression' &&
4324
+ /^(variables|this|local|arguments)\.[A-Za-z_][\w]*$/i.test((0, tree_sitter_helpers_1.getNodeText)(receiver, this.source))) {
4325
+ // CFML scope-prefixed member call — `variables.svc.save()` /
4326
+ // `arguments.svc.save()`: the receiver is a component field,
4327
+ // injected property, or typed argument reached through one of
4328
+ // CFML's file-local scopes. Keep the full receiver chain so
4329
+ // resolution can strip the scope prefix and infer the field's
4330
+ // component type from its declaration (#1108). Gated to these
4331
+ // scope keywords: such calls previously emitted a bare method
4332
+ // name, which either failed to resolve or resolved ambiguously.
4333
+ calleeName = `${(0, tree_sitter_helpers_1.getNodeText)(receiver, this.source)}.${methodName}`;
4334
+ }
3716
4335
  else {
3717
4336
  calleeName = methodName;
3718
4337
  }
@@ -3755,6 +4374,40 @@ class TreeSitterExtractor {
3755
4374
  if (conv && conv[1])
3756
4375
  calleeName = conv[1];
3757
4376
  }
4377
+ // C/C++ templated callees — a direct templated call (`fn<T, 256>(args)`,
4378
+ // the shape every CUDA kernel-launch site takes once its `<<<…>>>` config
4379
+ // is blanked) or a qualified one (`ns::fn<T>(args)`) — carry template
4380
+ // arguments in the callee text, which can never match the bare name the
4381
+ // function was DEFINED as, so the call edge silently never resolves. Strip
4382
+ // them: the same normalization base-class `extends` refs already get
4383
+ // (#1043). `operator<`/`operator<<` callees are excluded — their `<` is the
4384
+ // operator itself, not a template-argument list.
4385
+ if (calleeName &&
4386
+ calleeName.includes('<') &&
4387
+ (this.language === 'cpp' || this.language === 'c') &&
4388
+ !calleeName.includes('operator')) {
4389
+ calleeName = (0, c_cpp_1.stripCppTemplateArgs)(calleeName);
4390
+ }
4391
+ // C++ call/launch through a local function pointer: `auto kernel =
4392
+ // &flash_fwd_kernel<…>; … kernel<<<grid, block>>>(params);` — the callee
4393
+ // is an unresolvable local name. When the same enclosing symbol bound the
4394
+ // local from `&fn` (each branch assignment counts), emit the call against
4395
+ // every recorded target instead of the local.
4396
+ if (calleeName && this.language === 'cpp' && /^[A-Za-z_]\w*$/.test(calleeName)) {
4397
+ const targets = this.cppLocalFnPtrs.get(callerId)?.get(calleeName);
4398
+ if (targets && targets.size > 0) {
4399
+ for (const target of targets) {
4400
+ this.unresolvedReferences.push({
4401
+ fromNodeId: callerId,
4402
+ referenceName: target,
4403
+ referenceKind: 'calls',
4404
+ line: node.startPosition.row + 1,
4405
+ column: node.startPosition.column,
4406
+ });
4407
+ }
4408
+ return;
4409
+ }
4410
+ }
3758
4411
  if (calleeName) {
3759
4412
  this.unresolvedReferences.push({
3760
4413
  fromNodeId: callerId,
@@ -3774,6 +4427,26 @@ class TreeSitterExtractor {
3774
4427
  * Children are still walked so nested calls inside the constructor
3775
4428
  * arguments (`new Foo(bar())`) get their own `calls` references.
3776
4429
  */
4430
+ /**
4431
+ * VB.NET `New Invoice(1)` is syntactically ambiguous between constructing
4432
+ * Invoice with an argument and allocating an Invoice array of bound 1; the
4433
+ * grammar parses the parenthesized form as array_creation_expression. A
4434
+ * user-defined type with no `{...}` array initializer is overwhelmingly a
4435
+ * constructor call, so treat it as an instantiation. Predefined element
4436
+ * types (`New Byte(1023)`) and brace-initialized forms stay arrays.
4437
+ */
4438
+ isVbnetConstructorShapedArrayCreation(node) {
4439
+ if (this.language !== 'vbnet' || node.type !== 'array_creation_expression')
4440
+ return false;
4441
+ const typeNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'type');
4442
+ if (!typeNode || typeNode.type === 'predefined_type' || typeNode.type === 'array_type')
4443
+ return false;
4444
+ for (const child of node.namedChildren) {
4445
+ if (child?.type === 'array_initializer')
4446
+ return false;
4447
+ }
4448
+ return true;
4449
+ }
3777
4450
  extractInstantiation(node) {
3778
4451
  if (this.nodeStack.length === 0)
3779
4452
  return;
@@ -3836,6 +4509,14 @@ class TreeSitterExtractor {
3836
4509
  const ltIdx = className.indexOf('<');
3837
4510
  if (ltIdx > 0)
3838
4511
  className = className.slice(0, ltIdx);
4512
+ // VB.NET spells generics with parentheses: `New List(Of String)` /
4513
+ // `New Dictionary(Of K, V)(cap)` — strip from the `(` so the bare
4514
+ // type name is what resolution matches.
4515
+ if (this.language === 'vbnet') {
4516
+ const parenIdx = className.indexOf('(');
4517
+ if (parenIdx > 0)
4518
+ className = className.slice(0, parenIdx);
4519
+ }
3839
4520
  // For namespaced/qualified constructors (`new ns.Foo()`,
3840
4521
  // `new ns::Foo()`) keep the trailing identifier — that's what
3841
4522
  // matches a class node in the index.
@@ -3853,6 +4534,45 @@ class TreeSitterExtractor {
3853
4534
  });
3854
4535
  }
3855
4536
  }
4537
+ /**
4538
+ * Is this C++ `declaration` a stack/direct-initialization object construction
4539
+ * that invokes a constructor — `Calculator calc(0)` (direct-init) or
4540
+ * `Widget w{1, 2}` (brace-init) — as opposed to a plain variable or a
4541
+ * function declaration? Used to emit an `instantiates` edge for the
4542
+ * call-less construction syntax (#1035); heap `new T(...)` is handled
4543
+ * separately by INSTANTIATION_KINDS.
4544
+ *
4545
+ * Two signals, both required:
4546
+ * - the `type` field is a class-like NAMED type (`type_identifier`,
4547
+ * `template_type`, or `qualified_identifier`). Primitives (`int x(0)`),
4548
+ * `auto` (`placeholder_type_specifier` — that form always carries a real
4549
+ * `call_expression`, already handled), and sized specifiers are excluded —
4550
+ * they construct no class; and
4551
+ * - a declarator carries constructor arguments: an `init_declarator` whose
4552
+ * `value` is an `argument_list` (`(args)`) or `initializer_list` (`{args}`).
4553
+ * This skips default construction `Calculator c;` (no value) and the
4554
+ * most-vexing-parse `Calculator c();` (a bodyless `function_declarator`,
4555
+ * a function decl — not a construction).
4556
+ */
4557
+ isCppStackConstruction(node) {
4558
+ const typeNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'type');
4559
+ if (!typeNode ||
4560
+ (typeNode.type !== 'type_identifier' &&
4561
+ typeNode.type !== 'template_type' &&
4562
+ typeNode.type !== 'qualified_identifier')) {
4563
+ return false;
4564
+ }
4565
+ for (let i = 0; i < node.namedChildCount; i++) {
4566
+ const child = node.namedChild(i);
4567
+ if (child?.type !== 'init_declarator')
4568
+ continue;
4569
+ const value = (0, tree_sitter_helpers_1.getChildByField)(child, 'value');
4570
+ if (value && (value.type === 'argument_list' || value.type === 'initializer_list')) {
4571
+ return true;
4572
+ }
4573
+ }
4574
+ return false;
4575
+ }
3856
4576
  /**
3857
4577
  * Static-member / value-read pass. A type/enum/class used only via a member
3858
4578
  * VALUE — `Enum.value`, `Type.CONST`, `Colors.red`, `Foo::BAR` — recorded no
@@ -4011,6 +4731,28 @@ class TreeSitterExtractor {
4011
4731
  const consider = (n) => {
4012
4732
  if (!n)
4013
4733
  return;
4734
+ // Solidity `modifier_invocation` (unique to that grammar) sits
4735
+ // decorator-position in the function header — OUTSIDE the `body:` field
4736
+ // the call walker descends — but its body executes around the function
4737
+ // via `_;`, so it is a real call-flow hop (`withdraw → onlyOwner →
4738
+ // _checkRole` is the canonical audit trace). The same node type carries
4739
+ // base-constructor invocations (`constructor() ERC20("T","TOK")`), the
4740
+ // constructor-chain hop. Emit `calls`, not `decorates`, so flow
4741
+ // traversal rides it.
4742
+ if (n.type === 'modifier_invocation') {
4743
+ const target = n.namedChild(0);
4744
+ const name = target?.type === 'identifier' ? (0, tree_sitter_helpers_1.getNodeText)(target, this.source) : undefined;
4745
+ if (name) {
4746
+ this.unresolvedReferences.push({
4747
+ fromNodeId: decoratedId,
4748
+ referenceName: name,
4749
+ referenceKind: 'calls',
4750
+ line: n.startPosition.row + 1,
4751
+ column: n.startPosition.column,
4752
+ });
4753
+ }
4754
+ return;
4755
+ }
4014
4756
  // `marker_annotation` is Java's grammar for arg-less annotations
4015
4757
  // (`@Override`, `@Deprecated`); `attribute` is Swift's grammar for
4016
4758
  // attributes and PROPERTY WRAPPERS (`@objc`, `@Argument`, `@Published`,
@@ -4188,6 +4930,43 @@ class TreeSitterExtractor {
4188
4930
  }
4189
4931
  flush();
4190
4932
  }
4933
+ /**
4934
+ * Record a C++ local function-pointer binding (`local = &fn` / `&fn<…>` /
4935
+ * `&ns::fn<…>`) for the CURRENT enclosing symbol, so calls through the local
4936
+ * resolve to the real target (see cppLocalFnPtrs). Only the address-of shape
4937
+ * is accepted — a bare-identifier RHS (`auto x = y;`) is any value copy, and
4938
+ * linking through it would guess.
4939
+ */
4940
+ recordCppFnPtrBinding(localName, value) {
4941
+ if (!value || value.type !== 'pointer_expression')
4942
+ return;
4943
+ if (value.child(0)?.type !== '&')
4944
+ return; // `*p` dereference, not address-of
4945
+ const arg = (0, tree_sitter_helpers_1.getChildByField)(value, 'argument') ?? value.namedChild(0);
4946
+ if (!arg ||
4947
+ (arg.type !== 'identifier' &&
4948
+ arg.type !== 'template_function' &&
4949
+ arg.type !== 'qualified_identifier')) {
4950
+ return;
4951
+ }
4952
+ const callerId = this.nodeStack[this.nodeStack.length - 1];
4953
+ if (!callerId)
4954
+ return;
4955
+ const target = (0, c_cpp_1.stripCppTemplateArgs)((0, tree_sitter_helpers_1.getNodeText)(arg, this.source));
4956
+ if (!target || target === localName)
4957
+ return;
4958
+ let locals = this.cppLocalFnPtrs.get(callerId);
4959
+ if (!locals) {
4960
+ locals = new Map();
4961
+ this.cppLocalFnPtrs.set(callerId, locals);
4962
+ }
4963
+ let targets = locals.get(localName);
4964
+ if (!targets) {
4965
+ targets = new Set();
4966
+ locals.set(localName, targets);
4967
+ }
4968
+ targets.add(target);
4969
+ }
4191
4970
  visitFunctionBody(body, _functionId) {
4192
4971
  if (!this.extractor)
4193
4972
  return;
@@ -4203,7 +4982,7 @@ class TreeSitterExtractor {
4203
4982
  if (this.extractor.callTypes.includes(nodeType)) {
4204
4983
  this.extractCall(node);
4205
4984
  }
4206
- else if (INSTANTIATION_KINDS.has(nodeType)) {
4985
+ else if (INSTANTIATION_KINDS.has(nodeType) || this.isVbnetConstructorShapedArrayCreation(node)) {
4207
4986
  // `new Foo()` inside a function body — emit an `instantiates`
4208
4987
  // reference. Without this branch the body walker only knew
4209
4988
  // about `call_expression`, so constructor invocations
@@ -4233,6 +5012,43 @@ class TreeSitterExtractor {
4233
5012
  }
4234
5013
  }
4235
5014
  }
5015
+ // C++ stack / direct-initialization construction — `Calculator calc(0)`
5016
+ // and `Widget w{1, 2}`. Unlike heap `new Calculator(0)` (a new_expression
5017
+ // handled above), these carry the constructor arguments directly on the
5018
+ // declarator with NO call/new node, so the body walker saw no constructor
5019
+ // invocation and recorded no `instantiates` edge (#1035). A declaration's
5020
+ // `type` field IS the constructed class name, so reuse extractInstantiation
5021
+ // (which strips template args / namespace and emits the `instantiates`
5022
+ // ref). Children still recurse below, so a nested ctor-arg call
5023
+ // (`Calculator calc(make())`) keeps its own `calls` ref.
5024
+ if (nodeType === 'declaration' && this.language === 'cpp' && this.isCppStackConstruction(node)) {
5025
+ this.extractInstantiation(node);
5026
+ }
5027
+ // C++ local function-pointer bindings (see cppLocalFnPtrs): record
5028
+ // `auto kernel = &fn<…>;` declarations and `kernel = &other_fn<…>;`
5029
+ // branch reassignments so a call/launch through the local links to the
5030
+ // real target(s). The body walker sees these in source order, and C++
5031
+ // requires declaration-before-use, so the map is always populated before
5032
+ // the call that consumes it.
5033
+ if (this.language === 'cpp' && this.nodeStack.length > 0) {
5034
+ if (nodeType === 'declaration') {
5035
+ for (let i = 0; i < node.namedChildCount; i++) {
5036
+ const child = node.namedChild(i);
5037
+ if (child?.type !== 'init_declarator')
5038
+ continue;
5039
+ const decl = (0, tree_sitter_helpers_1.getChildByField)(child, 'declarator');
5040
+ if (decl?.type !== 'identifier')
5041
+ continue;
5042
+ this.recordCppFnPtrBinding((0, tree_sitter_helpers_1.getNodeText)(decl, this.source), (0, tree_sitter_helpers_1.getChildByField)(child, 'value'));
5043
+ }
5044
+ }
5045
+ else if (nodeType === 'assignment_expression') {
5046
+ const left = (0, tree_sitter_helpers_1.getChildByField)(node, 'left');
5047
+ if (left?.type === 'identifier') {
5048
+ this.recordCppFnPtrBinding((0, tree_sitter_helpers_1.getNodeText)(left, this.source), (0, tree_sitter_helpers_1.getChildByField)(node, 'right'));
5049
+ }
5050
+ }
5051
+ }
4236
5052
  // Static-member / value-read: `Enum.value`, `Type.CONST`, `Foo::BAR`.
4237
5053
  this.extractStaticMemberRef(node);
4238
5054
  // Local variable type annotations inside a body — `const items: Foo[] = []`,
@@ -4427,7 +5243,11 @@ class TreeSitterExtractor {
4427
5243
  }
4428
5244
  // C++ base classes: `class Derived : public Base, private Other` →
4429
5245
  // base_class_clause holds access specifiers + base type(s). Emit an extends
4430
- // ref per base type (skip the public/private/protected keywords).
5246
+ // ref per base type (skip the public/private/protected keywords). A
5247
+ // templated base (`Base<int>`, `ns::Tpl<int>`) arrives as a `template_type`
5248
+ // or a `qualified_identifier` wrapping one; strip the `<…>` args so the ref
5249
+ // matches the bare class the template was defined as — `Base`, `ns::Tpl` —
5250
+ // instead of never resolving (#1043).
4431
5251
  if (child.type === 'base_class_clause') {
4432
5252
  for (const t of child.namedChildren) {
4433
5253
  if (t.type === 'type_identifier' ||
@@ -4435,7 +5255,7 @@ class TreeSitterExtractor {
4435
5255
  t.type === 'template_type') {
4436
5256
  this.unresolvedReferences.push({
4437
5257
  fromNodeId: classId,
4438
- referenceName: (0, tree_sitter_helpers_1.getNodeText)(t, this.source),
5258
+ referenceName: (0, c_cpp_1.stripCppTemplateArgs)((0, tree_sitter_helpers_1.getNodeText)(t, this.source)),
4439
5259
  referenceKind: 'extends',
4440
5260
  line: t.startPosition.row + 1,
4441
5261
  column: t.startPosition.column,
@@ -4553,6 +5373,33 @@ class TreeSitterExtractor {
4553
5373
  }
4554
5374
  }
4555
5375
  }
5376
+ // VB.NET: `Inherits Base` / `Implements IFoo, IBar(Of T)` are STATEMENTS
5377
+ // inside the class body (children of the class node), not header clauses.
5378
+ // Each name is a simple/qualified/generic reference; generics unwrap to
5379
+ // the base identifier and dotted paths keep the trailing segment.
5380
+ if (this.language === 'vbnet' &&
5381
+ (child.type === 'inherits_statement' || child.type === 'implements_statement')) {
5382
+ const kind = child.type === 'inherits_statement' ? 'extends' : 'implements';
5383
+ for (const ref of child.namedChildren) {
5384
+ if (!ref || (ref.type !== 'simple_name' && ref.type !== 'qualified_name' && ref.type !== 'generic_name' && ref.type !== 'global_qualified_name'))
5385
+ continue;
5386
+ let name = (0, tree_sitter_helpers_1.getNodeText)(ref, this.source);
5387
+ name = name.replace(/\(\s*Of\b[^)]*\)/gi, '');
5388
+ const lastDot = name.lastIndexOf('.');
5389
+ if (lastDot >= 0)
5390
+ name = name.slice(lastDot + 1);
5391
+ name = name.trim();
5392
+ if (!name)
5393
+ continue;
5394
+ this.unresolvedReferences.push({
5395
+ fromNodeId: classId,
5396
+ referenceName: name,
5397
+ referenceKind: kind,
5398
+ line: ref.startPosition.row + 1,
5399
+ column: ref.startPosition.column,
5400
+ });
5401
+ }
5402
+ }
4556
5403
  // C#: `class Movie : BaseItem, IPlugin` → base_list with identifier children
4557
5404
  // base_list combines both base class and interfaces in a single colon-separated list.
4558
5405
  // We emit all as 'extends' since the syntax doesn't distinguish them.
@@ -4628,6 +5475,33 @@ class TreeSitterExtractor {
4628
5475
  if (child.type === 'field_declaration_list' || child.type === 'class_heritage') {
4629
5476
  this.extractInheritance(child, classId);
4630
5477
  }
5478
+ // CFML cfscript `component extends="Base" implements="IFoo,IBar" { ... }`
5479
+ // (also covers `interface extends="IBase" { ... }`, which reuses the same
5480
+ // component_attribute shape). Attributes are generic name=value pairs —
5481
+ // (identifier label, expression value) — not a dedicated extends_clause,
5482
+ // so filter by the label text. `implements` is a comma-separated list.
5483
+ if (child.type === 'component_attribute' && node.type === 'component') {
5484
+ const label = child.namedChildren.find((c) => c.type === 'identifier');
5485
+ const value = child.namedChildren.find((c) => c.type !== 'identifier');
5486
+ if (label && value) {
5487
+ const labelText = (0, tree_sitter_helpers_1.getNodeText)(label, this.source).toLowerCase();
5488
+ if (labelText === 'extends' || labelText === 'implements') {
5489
+ const valueText = (0, tree_sitter_helpers_1.getNodeText)(value, this.source).replace(/^["']|["']$/g, '');
5490
+ const names = labelText === 'implements'
5491
+ ? valueText.split(',').map((s) => s.trim()).filter(Boolean)
5492
+ : [valueText.trim()].filter(Boolean);
5493
+ for (const name of names) {
5494
+ this.unresolvedReferences.push({
5495
+ fromNodeId: classId,
5496
+ referenceName: name,
5497
+ referenceKind: labelText === 'implements' ? 'implements' : 'extends',
5498
+ line: value.startPosition.row + 1,
5499
+ column: value.startPosition.column,
5500
+ });
5501
+ }
5502
+ }
5503
+ }
5504
+ }
4631
5505
  }
4632
5506
  }
4633
5507
  /**
@@ -4687,7 +5561,7 @@ class TreeSitterExtractor {
4687
5561
  * Languages that support type annotations (TypeScript, etc.)
4688
5562
  */
4689
5563
  TYPE_ANNOTATION_LANGUAGES = new Set([
4690
- 'typescript', 'tsx', 'dart', 'kotlin', 'swift', 'rust', 'go', 'java', 'csharp', 'scala', 'php',
5564
+ 'typescript', 'tsx', 'arkts', 'dart', 'kotlin', 'swift', 'rust', 'go', 'java', 'csharp', 'scala', 'php',
4691
5565
  ]);
4692
5566
  /**
4693
5567
  * PHP pseudo-types and `self`/`static`/`parent` that aren't project symbols.
@@ -5546,7 +6420,7 @@ exports.TreeSitterExtractor = TreeSitterExtractor;
5546
6420
  * those names and the file's language are run after the tree-sitter pass.
5547
6421
  * Their nodes/references/errors are merged into the returned result.
5548
6422
  */
5549
- function extractFromSource(filePath, source, language, frameworkNames) {
6423
+ function extractFromSource(filePath, source, language, frameworkNames, vbaTargets) {
5550
6424
  const detectedLanguage = language || (0, grammars_1.detectLanguage)(filePath, source);
5551
6425
  const fileExtension = path.extname(filePath).toLowerCase();
5552
6426
  let result;
@@ -5581,6 +6455,17 @@ function extractFromSource(filePath, source, language, frameworkNames) {
5581
6455
  const extractor = new mybatis_extractor_1.MyBatisExtractor(filePath, source);
5582
6456
  result = extractor.extract();
5583
6457
  }
6458
+ else if (detectedLanguage === 'cfml' || detectedLanguage === 'cfscript') {
6459
+ // Custom extractor for CFML (.cfc/.cfm) — dialect-switches between the
6460
+ // tag-based cfml grammar and the bare-script cfscript grammar. Standalone
6461
+ // `.cfs` files (language 'cfscript') are always pure script (never `<`-led),
6462
+ // so routing them through here too gets them the same anonymous-component
6463
+ // filename fallback as a bare-script `.cfc` — without it a `.cfs` whose
6464
+ // `component { ... }` declares no name (the grammar has no `name` field;
6465
+ // CFML never spells one in source) stays `<anonymous>`.
6466
+ const extractor = new cfml_extractor_1.CfmlExtractor(filePath, source, detectedLanguage);
6467
+ result = extractor.extract();
6468
+ }
5584
6469
  else if ((0, grammars_1.isFileLevelOnlyLanguage)(detectedLanguage)) {
5585
6470
  // No symbol extraction at this stage — files are tracked at the file-record
5586
6471
  // level only. Framework extractors (Drupal routing yml, Spring `@Value`
@@ -5607,7 +6492,7 @@ function extractFromSource(filePath, source, language, frameworkNames) {
5607
6492
  else if (detectedLanguage === 'vba') {
5608
6493
  // VBA standard/class/legacy modules — `.bas`, `.cls`, `.frm`, `.dsr`.
5609
6494
  // See `vba-code-extraction` spec (REQ-CODE-1..11).
5610
- const extractor = new vba_extractor_1.VbaExtractor(filePath, source);
6495
+ const extractor = new vba_extractor_1.VbaExtractor(filePath, source, vbaTargets);
5611
6496
  result = extractor.extract();
5612
6497
  }
5613
6498
  else if (detectedLanguage === 'sql') {