@aroman22/codegraph-vba-darwin-arm64 1.5.1 → 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 +127 -4
  19. package/lib/dist/db/queries.d.ts.map +1 -1
  20. package/lib/dist/db/queries.js +317 -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 +467 -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 +85 -2
  268. package/lib/dist/resolution/index.d.ts.map +1 -1
  269. package/lib/dist/resolution/index.js +535 -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
@@ -12,6 +12,8 @@ exports.crossesKnownFamily = crossesKnownFamily;
12
12
  exports.matchFunctionRef = matchFunctionRef;
13
13
  exports.matchByExactName = matchByExactName;
14
14
  exports.matchByQualifiedName = matchByQualifiedName;
15
+ exports.preferCallSiteFile = preferCallSiteFile;
16
+ exports.resolveMethodOnType = resolveMethodOnType;
15
17
  exports.matchCppCallChain = matchCppCallChain;
16
18
  exports.matchScopedCallChain = matchScopedCallChain;
17
19
  exports.matchDottedCallChain = matchDottedCallChain;
@@ -138,7 +140,9 @@ function pickClosestFileNode(candidates, ref) {
138
140
  const LANGUAGE_FAMILY = {
139
141
  java: 'jvm', kotlin: 'jvm', scala: 'jvm',
140
142
  swift: 'apple', objc: 'apple',
141
- typescript: 'web', tsx: 'web', javascript: 'web', jsx: 'web',
143
+ // ArkTS is a TS superset every HarmonyOS project mixes `.ets` UI with
144
+ // `.ts` logic modules, so refs must cross freely between them.
145
+ typescript: 'web', tsx: 'web', javascript: 'web', jsx: 'web', arkts: 'web',
142
146
  c: 'c', cpp: 'c',
143
147
  // Razor/Blazor markup names C# types — same family so `@model Foo` /
144
148
  // `<MyComponent/>` resolve to their `.cs` class through the cross-family gate.
@@ -220,6 +224,7 @@ function matchFunctionRef(ref, context) {
220
224
  // implicit-self, Java/Kotlin method references.
221
225
  const bareFnOnly = ref.language === 'typescript' || ref.language === 'tsx' ||
222
226
  ref.language === 'javascript' || ref.language === 'jsx' ||
227
+ ref.language === 'arkts' ||
223
228
  ref.language === 'cpp' || ref.language === 'python' ||
224
229
  ref.language === 'php';
225
230
  // Qualified member-pointer (`&Widget::on_click` → "Widget::on_click"):
@@ -382,7 +387,17 @@ function matchByQualifiedName(ref, context) {
382
387
  if (!ref.referenceName.includes('::') && !ref.referenceName.includes('.')) {
383
388
  return null;
384
389
  }
385
- const candidates = context.getNodesByQualifiedName(ref.referenceName);
390
+ // A method call `receiver.method()` can share an exact qualified name with a
391
+ // config-file key: `service.process()` (a `calls` ref named `service.process`)
392
+ // vs the yaml key `service.process`. Config keys are bound to their code refs
393
+ // upstream by the framework resolvers (`@Value` → `references`); a `calls` ref
394
+ // must never resolve to a yaml/properties config node — that's a wrong edge
395
+ // AND it hides the real callee. Drop those from both the exact and the partial
396
+ // candidate sets so resolution falls through to method resolution below (#1180).
397
+ const keepForRef = (nodes) => ref.referenceKind === 'calls'
398
+ ? nodes.filter((n) => !(n.kind === 'constant' && (n.language === 'yaml' || n.language === 'properties')))
399
+ : nodes;
400
+ const candidates = keepForRef(context.getNodesByQualifiedName(ref.referenceName));
386
401
  if (candidates.length === 1) {
387
402
  return {
388
403
  original: ref,
@@ -391,24 +406,63 @@ function matchByQualifiedName(ref, context) {
391
406
  resolvedBy: 'qualified-name',
392
407
  };
393
408
  }
394
- // Try partial qualified name match
409
+ // Several symbols share this exact qualified name (e.g. `Logger::log` declared
410
+ // in two files — an ODR clash or separate translation units): prefer the one
411
+ // in the call site's own file before the partial-match fallback below, else
412
+ // the first-indexed def wins and a call in `b/svc` targets `a/svc` (#1079).
413
+ if (candidates.length > 1) {
414
+ const ordered = preferCallSiteFile(candidates, ref.filePath);
415
+ if (ordered[0].filePath === ref.filePath) {
416
+ return {
417
+ original: ref,
418
+ targetNodeId: ordered[0].id,
419
+ confidence: 0.95,
420
+ resolvedBy: 'qualified-name',
421
+ };
422
+ }
423
+ }
424
+ // Try partial qualified name match — again preferring the call site's own
425
+ // file when more than one symbol's qualifiedName ends with the reference.
395
426
  const parts = ref.referenceName.split(/[:.]/);
396
427
  const lastName = parts[parts.length - 1];
397
428
  if (lastName) {
398
- const partialCandidates = context.getNodesByName(lastName);
399
- for (const candidate of partialCandidates) {
400
- if (candidate.qualifiedName.endsWith(ref.referenceName)) {
401
- return {
402
- original: ref,
403
- targetNodeId: candidate.id,
404
- confidence: 0.85,
405
- resolvedBy: 'qualified-name',
406
- };
407
- }
429
+ const partialCandidates = keepForRef(context.getNodesByName(lastName))
430
+ .filter((candidate) => candidate.qualifiedName.endsWith(ref.referenceName));
431
+ const chosen = preferCallSiteFile(partialCandidates, ref.filePath)[0];
432
+ if (chosen) {
433
+ return {
434
+ original: ref,
435
+ targetNodeId: chosen.id,
436
+ confidence: 0.85,
437
+ resolvedBy: 'qualified-name',
438
+ };
408
439
  }
409
440
  }
410
441
  return null;
411
442
  }
443
+ /**
444
+ * When a symbol name is ambiguous across files, prefer the candidate(s) declared
445
+ * in the call site's own file, keeping the rest in their original order (#1079).
446
+ * A same-file definition is the strongest language-agnostic signal for which of
447
+ * several same-named symbols a call means; without it, resolution collapses onto
448
+ * whichever was indexed first, so a call in `b/svc` wrongly targets `a/svc`.
449
+ * No-op when there are <2 candidates or none share the call site's file.
450
+ */
451
+ function preferCallSiteFile(nodes, callSiteFile) {
452
+ if (nodes.length < 2)
453
+ return nodes;
454
+ const same = [];
455
+ const other = [];
456
+ for (const n of nodes) {
457
+ if (n.filePath === callSiteFile)
458
+ same.push(n);
459
+ else
460
+ other.push(n);
461
+ }
462
+ return same.length ? [...same, ...other] : nodes;
463
+ }
464
+ // Exported for the precedence unit tests (#1079): they assert the
465
+ // preferredFqn → same-file → matches[0] ordering directly.
412
466
  function resolveMethodOnType(typeName, methodName, ref, context, confidence, resolvedBy,
413
467
  /**
414
468
  * Optional FQN that identifies WHICH class declaration `typeName`
@@ -426,17 +480,28 @@ depth = 0) {
426
480
  // in-class (`class Foo { int bar() { ... } }`) or out-of-line in a separate
427
481
  // file (`int Foo::bar() { ... }` in foo.cpp while class Foo is in foo.hpp).
428
482
  // The previous same-file approach missed the latter — the typical C++ layout.
429
- const methodCandidates = context.getNodesByName(methodName);
430
- const want = `${typeName}::${methodName}`;
431
- const matches = [];
432
- for (const m of methodCandidates) {
433
- if (m.kind !== 'method')
434
- continue;
435
- if (m.language !== ref.language)
436
- continue;
437
- const qn = m.qualifiedName;
438
- if (qn === want || qn.endsWith(`::${want}`)) {
439
- matches.push(m);
483
+ // Prefer the context's per-(type, method) memo: the raw name lookup fetches
484
+ // EVERY node sharing the method name — tens of thousands of rows for a
485
+ // collision-heavy Java name like `execute` — and re-filtering that per ref
486
+ // was a dominant term in the #1122 watchdog kill on large repos. Only the
487
+ // ref-independent filter is memoized; per-ref disambiguation stays below.
488
+ let matches;
489
+ if (context.getMethodMatches) {
490
+ matches = context.getMethodMatches(typeName, methodName, ref.language);
491
+ }
492
+ else {
493
+ const methodCandidates = context.getNodesByName(methodName);
494
+ const want = `${typeName}::${methodName}`;
495
+ matches = [];
496
+ for (const m of methodCandidates) {
497
+ if (m.kind !== 'method')
498
+ continue;
499
+ if (m.language !== ref.language)
500
+ continue;
501
+ const qn = m.qualifiedName;
502
+ if (qn === want || qn.endsWith(`::${want}`)) {
503
+ matches.push(m);
504
+ }
440
505
  }
441
506
  }
442
507
  if (matches.length === 0) {
@@ -472,9 +537,19 @@ depth = 0) {
472
537
  };
473
538
  }
474
539
  }
540
+ // Language-agnostic disambiguation: when several same-named methods survive
541
+ // (e.g. two files each declaring `class Logger { void log(); }` — an ODR
542
+ // clash, an anonymous-namespace type, or separate translation units), prefer
543
+ // the definition in the CALL SITE's own file. Without this, every ambiguous
544
+ // call collapses onto the first-indexed definition, so a call in `b/svc.cpp`
545
+ // wrongly points at `a/svc.cpp` (#1079). This runs AFTER the `preferredFqn`
546
+ // block, so Java/Kotlin import disambiguation — whose target is intentionally
547
+ // in ANOTHER file (#314) — is unaffected: that block returns early whenever
548
+ // an import FQN pins the class.
549
+ const ordered = preferCallSiteFile(matches, ref.filePath);
475
550
  return {
476
551
  original: ref,
477
- targetNodeId: matches[0].id,
552
+ targetNodeId: ordered[0].id,
478
553
  confidence,
479
554
  resolvedBy,
480
555
  };
@@ -513,10 +588,14 @@ function buildDeclaratorRegex(escapedReceiver) {
513
588
  return new RegExp(`([A-Za-z_][\\w:]*(?:\\s*<[^;=(){}]+>)?(?:\\s*[*&]+)?)\\s*\\b${escapedReceiver}\\b\\s*(?=[;=,)\\[{(]|$)`);
514
589
  }
515
590
  function inferCppReceiverType(receiverName, ref, context, depth = 0) {
516
- const source = context.readFile(ref.filePath);
517
- if (!source)
591
+ // Per-file lines cache when available — this runs per `receiver->method()`
592
+ // ref and re-splitting the file each time is the same quadratic as the
593
+ // shared inferrer's (#1122).
594
+ const lines = context.getFileLines
595
+ ? context.getFileLines(ref.filePath)
596
+ : (context.readFile(ref.filePath)?.split(/\r?\n/) ?? null);
597
+ if (!lines || lines.length === 0)
518
598
  return null;
519
- const lines = source.split(/\r?\n/);
520
599
  const callLineIndex = Math.max(0, Math.min(lines.length - 1, ref.line - 1));
521
600
  const escapedReceiver = receiverName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
522
601
  const receiverPattern = new RegExp(`\\b${escapedReceiver}\\b`);
@@ -549,10 +628,12 @@ function inferCppReceiverType(receiverName, ref, context, depth = 0) {
549
628
  for (const headerPath of headerCandidates) {
550
629
  if (!context.fileExists(headerPath))
551
630
  continue;
552
- const headerSource = context.readFile(headerPath);
553
- if (!headerSource)
631
+ const headerLines = context.getFileLines
632
+ ? context.getFileLines(headerPath)
633
+ : (context.readFile(headerPath)?.split(/\r?\n/) ?? null);
634
+ if (!headerLines)
554
635
  continue;
555
- for (const line of headerSource.split(/\r?\n/)) {
636
+ for (const line of headerLines) {
556
637
  if (!receiverPattern.test(line))
557
638
  continue;
558
639
  const declaratorMatch = line.match(declaratorRegex);
@@ -880,6 +961,394 @@ function inferJavaFieldReceiverType(receiverName, ref, context) {
880
961
  return null; // primitives / lowercase → skip
881
962
  return lastPart;
882
963
  }
964
+ // ── Local-variable receiver-type inference (#1108) ──────────────────────────
965
+ //
966
+ // Instance calls through a local variable (`const lg = new Logger(); lg.log()`)
967
+ // only resolved in C++ before this — no other language could learn the
968
+ // receiver's type. Local variables are not indexed as nodes (node-explosion),
969
+ // so, like the C++ inferrer above, we read the enclosing function's source and
970
+ // match the receiver's declaration/initializer to recover its type. The type is
971
+ // then handed to resolveMethodOnType, which VALIDATES that the type actually
972
+ // declares the method, so a mis-inference produces NO edge — the safety net
973
+ // that lets the patterns below stay simple. C++ keeps its dedicated inferrer
974
+ // (header scan + `auto`); this covers every other language.
975
+ // Tokens a loose pattern might capture that are never a user-defined type.
976
+ const NON_TYPE_RECEIVER_TOKENS = new Set([
977
+ 'this', 'self', 'super', 'new', 'return', 'await', 'yield', 'typeof',
978
+ 'null', 'nil', 'None', 'true', 'false', 'True', 'False', 'undefined',
979
+ ]);
980
+ /**
981
+ * Normalize a captured type expression to a simple type name: drop generic
982
+ * args and pointer/ref markers, take the last `.`/`::`-qualified segment, and
983
+ * reject obvious non-types.
984
+ */
985
+ function normalizeInferredTypeName(raw) {
986
+ const cleaned = raw.replace(/<[^>]*>/g, '').replace(/[&*]/g, '').trim();
987
+ const seg = cleaned.split(/[.:]+/).filter(Boolean).pop();
988
+ if (!seg)
989
+ return null;
990
+ if (NON_TYPE_RECEIVER_TOKENS.has(seg))
991
+ return null;
992
+ return seg;
993
+ }
994
+ /**
995
+ * Per-language patterns that recover a local variable's (or typed parameter's)
996
+ * type from its declaration/initializer. Each regex captures the type in group
997
+ * 1; `r` is the already-escaped receiver name. Ordered most-specific first.
998
+ * PascalCase is required in the capture where the language convention allows,
999
+ * as a cheap false-positive guard on top of resolveMethodOnType's validation.
1000
+ */
1001
+ function localReceiverTypePatterns(language, r) {
1002
+ switch (language) {
1003
+ case 'typescript':
1004
+ case 'javascript':
1005
+ case 'tsx':
1006
+ case 'jsx':
1007
+ case 'arkts':
1008
+ return [
1009
+ new RegExp(`\\b${r}\\b\\s*=\\s*new\\s+([A-Za-z_$][\\w.$]*)`), // = new Logger()
1010
+ // No keyword requirement, so this matches BOTH a local annotation
1011
+ // (`const lg: Logger`) and a typed parameter (`function use(lg: Logger)`
1012
+ // / `(lg: Logger) =>`) — the parameter case the old `const|let|var`
1013
+ // prefix excluded (#1125). Mirrors Kotlin/Swift/Scala; the capture stops
1014
+ // at `<` so a generic-typed param (`repo: Repository<User>`) still yields
1015
+ // `Repository`. resolveMethodOnType validates the type actually declares
1016
+ // the method, so the looser match produces no edge on a mis-inference.
1017
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.$]*)`), // lg: Logger (annotation or typed param)
1018
+ ];
1019
+ case 'python':
1020
+ return [
1021
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w.]*)\\s*\\(`), // lg = Logger(...)
1022
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.]*)`), // lg: Logger (PEP 526)
1023
+ ];
1024
+ case 'java':
1025
+ return [
1026
+ new RegExp(`\\b${r}\\b\\s*=\\s*new\\s+([A-Za-z_][\\w.]*)`), // = new Logger()
1027
+ new RegExp(`\\b([A-Z][\\w.]*)\\s+${r}\\b\\s*[=;,)]`), // Logger lg; / param
1028
+ ];
1029
+ case 'kotlin':
1030
+ return [
1031
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w.]*)\\s*\\(`), // val lg = Logger(...)
1032
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.]*)`), // val lg: Logger / param
1033
+ ];
1034
+ case 'csharp':
1035
+ return [
1036
+ new RegExp(`\\b${r}\\b\\s*=\\s*new\\s+([A-Za-z_][\\w.]*)`), // = new Logger()
1037
+ new RegExp(`\\b([A-Z][\\w.]*)\\s+${r}\\b\\s*[=;,)]`), // Logger lg; / param
1038
+ ];
1039
+ case 'swift':
1040
+ return [
1041
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w.]*)\\s*\\(`), // let lg = Logger(...)
1042
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.]*)`), // let lg: Logger / param
1043
+ ];
1044
+ case 'rust':
1045
+ return [
1046
+ new RegExp(`\\blet\\s+(?:mut\\s+)?${r}\\b(?:\\s*:[^=]+)?=\\s*&?(?:mut\\s+)?([A-Z][\\w]*)`), // let lg = Logger::new()/Logger{}/Logger
1047
+ // No `let`, so this covers a `let lg: Logger` binding AND a typed
1048
+ // parameter (`fn use(lg: &Logger)`, a closure `|lg: Logger|`) — the
1049
+ // parameter case the old `let`-anchored pattern excluded (#1125).
1050
+ new RegExp(`\\b${r}\\s*:\\s*&?(?:mut\\s+)?([A-Z][\\w]*)`), // lg: Logger (binding or typed param)
1051
+ ];
1052
+ case 'go':
1053
+ return [
1054
+ new RegExp(`\\b${r}\\b\\s*:=\\s*&?([A-Za-z_][\\w.]*)\\s*{`), // lg := Logger{} / &Logger{}
1055
+ new RegExp(`\\bvar\\s+${r}\\s+\\*?([A-Za-z_][\\w.]*)`), // var lg Logger / *Logger
1056
+ // A typed parameter / method receiver (`func use(lg Logger)`,
1057
+ // `func (l Logger) M()`) — name-before-type with no `var`/`:=` (#1125).
1058
+ // PascalCase-guarded (unlike the anchored patterns above) to keep the
1059
+ // keyword-free `ident Type` shape from matching unrelated pairs; the
1060
+ // enclosing-scope bound already excludes package-level struct fields.
1061
+ new RegExp(`\\b${r}\\s+\\*?([A-Z][\\w.]*)`), // func use(lg Logger) / (l Logger)
1062
+ ];
1063
+ case 'ruby':
1064
+ return [
1065
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w:]*)\\.new\\b`), // lg = Logger.new
1066
+ ];
1067
+ case 'scala':
1068
+ return [
1069
+ new RegExp(`\\b${r}\\b\\s*=\\s*(?:new\\s+)?([A-Z][\\w.]*)`), // val lg = new Logger / Logger(...)
1070
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.]*)`), // val lg: Logger / param
1071
+ ];
1072
+ case 'dart':
1073
+ return [
1074
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w.]*)\\s*\\(`), // var lg = Logger(...)
1075
+ // Trailing `[=;,)]` (not just `[=;]`) so a typed parameter — `Logger lg)`
1076
+ // / `Logger lg,` — matches too, not only `Logger lg = ...` / `Logger lg;`
1077
+ // (#1125). Mirrors Java/C#.
1078
+ new RegExp(`\\b([A-Z][\\w.]*)\\s+${r}\\b\\s*[=;,)]`), // Logger lg = ... / param
1079
+ ];
1080
+ case 'php':
1081
+ return [
1082
+ new RegExp(`\\$?${r}\\b\\s*=\\s*new\\s+([A-Za-z_\\\\][\\w\\\\]*)`), // $lg = new Logger()
1083
+ // A typed parameter (`function use(Logger $lg)`, `?Logger $lg`,
1084
+ // `\\App\\Logger $lg`, `&$lg` by-ref) and a typed `catch (E $e)` — the
1085
+ // type sits before the `$`-variable (#1125). Namespace `\\` allowed.
1086
+ new RegExp(`\\b([A-Za-z_\\\\][\\w\\\\]*)\\s+&?\\$${r}\\b`), // Logger $lg (typed param)
1087
+ ];
1088
+ case 'lua':
1089
+ case 'luau':
1090
+ return [
1091
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w]*)\\.new\\b`), // local lg = Logger.new()
1092
+ new RegExp(`\\b${r}\\b\\s*=\\s*([A-Z][\\w]*)\\s*\\(`), // local lg = Logger(...) (callable table)
1093
+ // Luau annotation (`local lg: Logger`) / typed param — but Lua's
1094
+ // method-call syntax is the IDENTICAL `receiver:Name` shape, and the
1095
+ // backward scan starts on the call's own line, so without a gate any
1096
+ // PascalCase method call (`lg:Log()`, the Roblox convention)
1097
+ // self-matches as "type = Log" before the scan reaches the real
1098
+ // declaration (#1124). The lookahead rejects a capture followed by
1099
+ // any of Lua's three call forms — `(args)`, `"s"`/`'s'`/`[[s]]`,
1100
+ // `{t}` — and its leading `[\w.]` alternative stops backtracking from
1101
+ // shrinking the capture to dodge the gate (`lg:Log()` would otherwise
1102
+ // still match, as `Lo`).
1103
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.]*)(?![\\w.]|\\s*[({"'\\[])`), // local lg: Logger / typed param
1104
+ ];
1105
+ case 'r':
1106
+ return [
1107
+ new RegExp(`\\b${r}\\b\\s*(?:<-|<<-|=)\\s*([A-Z][\\w.]*)\\$new\\b`), // lg <- Logger$new() (R6)
1108
+ ];
1109
+ case 'pascal':
1110
+ return [
1111
+ new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w]*)`), // var lg: TLogger / param lg: TLogger
1112
+ new RegExp(`\\b${r}\\b\\s*:=\\s*([A-Z][\\w.]*)\\.Create\\b`), // lg := TLogger.Create
1113
+ ];
1114
+ case 'cfml':
1115
+ case 'cfscript':
1116
+ return [
1117
+ // svc = new UserService() / new path.to.UserService() — dotted component
1118
+ // paths reduce to their final segment via normalizeInferredTypeName.
1119
+ // Also matches inside tag markup (`<cfset svc = new UserService()>`)
1120
+ // since the scan reads raw source lines.
1121
+ new RegExp(`\\b${r}\\b\\s*=\\s*new\\s+([A-Za-z_][\\w.]*)`),
1122
+ // The classic form: svc = createObject("component", "path.to.UserService")
1123
+ // (casing of createObject varies in the wild), plus the modern
1124
+ // single-argument form createObject("path.to.UserService").
1125
+ new RegExp(`\\b${r}\\b\\s*=\\s*[Cc]reate[Oo]bject\\s*\\(\\s*["']component["']\\s*,\\s*["']([\\w.]+)["']`),
1126
+ new RegExp(`\\b${r}\\b\\s*=\\s*[Cc]reate[Oo]bject\\s*\\(\\s*["']([\\w.]+)["']\\s*\\)`),
1127
+ // Typed cfscript parameter: `function save(UserService svc)` /
1128
+ // `required UserService svc` — CFML's built-in types (string, numeric,
1129
+ // any, struct…) are lowercase by convention, so the PascalCase guard
1130
+ // excludes them.
1131
+ new RegExp(`\\b([A-Z][\\w.]*)\\s+${r}\\b\\s*[=;,)]`),
1132
+ // Tag-form typed argument, either attribute order:
1133
+ // <cfargument name="svc" type="path.to.UserService">
1134
+ new RegExp(`\\bcfargument[^>\\n]*\\bname\\s*=\\s*["']${r}["'][^>\\n]*\\btype\\s*=\\s*["']([\\w.]+)["']`, 'i'),
1135
+ new RegExp(`\\bcfargument[^>\\n]*\\btype\\s*=\\s*["']([\\w.]+)["'][^>\\n]*\\bname\\s*=\\s*["']${r}["']`, 'i'),
1136
+ // Component property (incl. WireBox DI): `property name="svc"
1137
+ // inject="UserService";` / `<cfproperty name="svc" type="UserService">`,
1138
+ // either attribute order. An inject DSL value with a namespace
1139
+ // (`inject="svc@core"`) captures only the leading name and simply
1140
+ // fails type-validation — no edge, never a wrong one.
1141
+ new RegExp(`\\b(?:cf)?property\\b[^;\\n]*\\bname\\s*=\\s*["']${r}["'][^;\\n]*\\b(?:type|inject)\\s*=\\s*["']([\\w.]+)["']`, 'i'),
1142
+ new RegExp(`\\b(?:cf)?property\\b[^;\\n]*\\b(?:type|inject)\\s*=\\s*["']([\\w.]+)["'][^;\\n]*\\bname\\s*=\\s*["']${r}["']`, 'i'),
1143
+ ];
1144
+ default:
1145
+ return [];
1146
+ }
1147
+ }
1148
+ /** 1-based start line of the tightest function/method enclosing the call. */
1149
+ function enclosingScopeStartLine(ref, context) {
1150
+ let start = 1;
1151
+ for (const n of context.getNodesInFile(ref.filePath)) {
1152
+ if (n.kind !== 'function' && n.kind !== 'method')
1153
+ continue;
1154
+ if (n.language !== ref.language)
1155
+ continue;
1156
+ const end = n.endLine ?? n.startLine;
1157
+ if (n.startLine <= ref.line && end >= ref.line && n.startLine >= start) {
1158
+ start = n.startLine;
1159
+ }
1160
+ }
1161
+ return start;
1162
+ }
1163
+ /**
1164
+ * Infer a receiver's type from its local declaration/initializer in the
1165
+ * enclosing function body. Language-dispatched; returns null for languages
1166
+ * without patterns or when no declaration is found. Bounded to the enclosing
1167
+ * scope so a same-named variable in another function can't leak in.
1168
+ */
1169
+ function inferLocalReceiverType(receiverName, ref, context) {
1170
+ // CFML scope prefixes: `variables.svc` / `this.svc` name a COMPONENT-scoped
1171
+ // field whose assignment or `property` declaration usually lives outside the
1172
+ // calling function (the init-pseudoconstructor / WireBox-injection pattern),
1173
+ // and `local.svc` is an explicit function-local. Strip the prefix so the
1174
+ // declaration patterns match (`variables.svc = new X()`, `property
1175
+ // name="svc" …`, `var svc = …` all bind the bare name), and widen the scan
1176
+ // to the whole file for the component-scoped forms — nearest-declaration-
1177
+ // backward still wins, so a function-local shadowing the field is preferred.
1178
+ let scanReceiver = receiverName;
1179
+ let componentScoped = false;
1180
+ if (ref.language === 'cfml' || ref.language === 'cfscript') {
1181
+ const scoped = receiverName.match(/^(variables|this|local|arguments)\.(.+)$/i);
1182
+ if (scoped) {
1183
+ scanReceiver = scoped[2];
1184
+ const scope = scoped[1].toLowerCase();
1185
+ componentScoped = scope === 'variables' || scope === 'this';
1186
+ }
1187
+ }
1188
+ // PHP `$this->prop` receiver — the property's declaration lives outside the
1189
+ // calling method (a promoted constructor parameter `private readonly Foo $prop`,
1190
+ // a typed property `private Foo $prop;`, or a classic constructor parameter
1191
+ // `Foo $prop` assigned in __construct). Strip the prefix and widen the scan to
1192
+ // the whole file (the constructor may sit below the calling method), but —
1193
+ // unlike CFML's scopes above — switch to PROPERTY-shaped patterns: a plain
1194
+ // `$prop` local or parameter lives in a different namespace than `$this->prop`
1195
+ // and can never shadow it, so the generic local patterns would type the
1196
+ // property from unrelated same-named variables in other methods (a wrong
1197
+ // 0.9-confidence edge, not a missing one).
1198
+ let phpProperty = false;
1199
+ if (ref.language === 'php') {
1200
+ const scoped = receiverName.match(/^this->(.+)$/);
1201
+ if (scoped) {
1202
+ scanReceiver = scoped[1];
1203
+ componentScoped = true;
1204
+ phpProperty = true;
1205
+ }
1206
+ }
1207
+ const escapedReceiver = scanReceiver.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1208
+ const patterns = phpProperty
1209
+ ? phpPropertyTypePatterns(escapedReceiver)
1210
+ : localReceiverTypePatterns(ref.language, escapedReceiver);
1211
+ if (patterns.length === 0)
1212
+ return null;
1213
+ // Split through the context's per-file lines cache when available: this runs
1214
+ // for EVERY `receiver.method()` ref, and re-splitting the whole file per ref
1215
+ // was ~20% of total index CPU on Java-heavy repos (#1122).
1216
+ const lines = context.getFileLines
1217
+ ? context.getFileLines(ref.filePath)
1218
+ : (context.readFile(ref.filePath)?.split(/\r?\n/) ?? null);
1219
+ if (!lines || lines.length === 0)
1220
+ return null;
1221
+ const callIdx = Math.max(0, Math.min(lines.length - 1, ref.line - 1));
1222
+ const startIdx = componentScoped
1223
+ ? 0
1224
+ : Math.max(0, enclosingScopeStartLine(ref, context) - 1);
1225
+ const matchLine = (i) => {
1226
+ const line = lines[i];
1227
+ if (!line)
1228
+ return null;
1229
+ // A generated/minified line (one multi-KB statement) is not something a
1230
+ // human-written local declaration lives on, and regexing it per ref is
1231
+ // pure waste — skip it rather than scan it.
1232
+ if (line.length > 10_000)
1233
+ return null;
1234
+ for (const re of patterns) {
1235
+ const m = line.match(re);
1236
+ if (m && m[1]) {
1237
+ const type = normalizeInferredTypeName(m[1]);
1238
+ if (type)
1239
+ return type;
1240
+ }
1241
+ }
1242
+ return null;
1243
+ };
1244
+ // Nearest declaration wins: scan backward from the call to the scope start.
1245
+ for (let i = callIdx; i >= startIdx; i--) {
1246
+ const type = matchLine(i);
1247
+ if (type)
1248
+ return type;
1249
+ }
1250
+ // A component-scoped field's declaration is position-independent — the
1251
+ // `variables.svc = new X()` pseudoconstructor assignment or `property`
1252
+ // declaration may sit BELOW the calling function in the file — so when the
1253
+ // backward pass finds nothing, sweep the remainder of the file too.
1254
+ if (componentScoped) {
1255
+ for (let i = callIdx + 1; i < lines.length; i++) {
1256
+ const type = matchLine(i);
1257
+ if (type)
1258
+ return type;
1259
+ }
1260
+ }
1261
+ // A PHP property with no statically-typed declaration (classic pre-7.4
1262
+ // style) may still be typed by what gets ASSIGNED to it — follow the
1263
+ // `$this->prop = $var` assignment to the assigned variable's own typed
1264
+ // declaration (a classic or multi-line constructor parameter, or a typed
1265
+ // setter's parameter).
1266
+ if (phpProperty) {
1267
+ return inferPhpAssignedPropertyType(escapedReceiver, lines, callIdx);
1268
+ }
1269
+ return null;
1270
+ }
1271
+ /**
1272
+ * Patterns that recover a PHP class property's declared type for a
1273
+ * `$this->prop` receiver. Deliberately NOT localReceiverTypePatterns: only
1274
+ * property-shaped declarations qualify —
1275
+ * 1. a modifier-prefixed typed declaration, which covers both a typed
1276
+ * property (`private ?Foo $prop;`) and a promoted constructor parameter
1277
+ * (`private readonly Foo $prop`), and
1278
+ * 2. the pseudoconstructor assignment (`$this->prop = new Foo(...)`).
1279
+ * A bare `X $prop` parameter or `$prop = new X()` local elsewhere in the
1280
+ * file must NOT match: those variables can never alias `$this->prop`.
1281
+ * Union-typed properties (`Foo|Bar $prop`) yield no match and thus no edge —
1282
+ * silent beats wrong. The classic untyped-property-assigned-in-constructor
1283
+ * shape is handled by inferPhpAssignedPropertyType instead.
1284
+ */
1285
+ function phpPropertyTypePatterns(r) {
1286
+ return [
1287
+ new RegExp(`\\b(?:(?:private|protected|public|readonly|static|final)(?:\\(set\\))?\\s+)+\\??([A-Za-z_\\\\][\\w\\\\]*)\\s+&?\\$${r}\\b`), // private readonly ?Foo $prop (typed property / promoted param)
1288
+ new RegExp(`\\$this->${r}\\b\\s*=\\s*new\\s+([A-Za-z_\\\\][\\w\\\\]*)`), // $this->prop = new Foo()
1289
+ ];
1290
+ }
1291
+ /**
1292
+ * Second-chance typing for a PHP `$this->prop` receiver whose property
1293
+ * declaration carries no static type (classic pre-7.4 style): find the
1294
+ * `$this->prop = $var` assignment, then recover `$var`'s type from its own
1295
+ * declaration WITHIN the assignment's function — the constructor's (possibly
1296
+ * multi-line) parameter list, a typed setter's parameter, or a `= new X()`
1297
+ * local. The backward scan stops at the enclosing `function` line (checked
1298
+ * for a match first — a single-line `__construct(Foo $var) { ... }` carries
1299
+ * the typed parameter itself), so a same-named variable in another method
1300
+ * can never type the property.
1301
+ */
1302
+ function inferPhpAssignedPropertyType(escapedProp, lines, callIdx) {
1303
+ const assignRe = new RegExp(`\\$this->${escapedProp}\\b\\s*=\\s*\\$(\\w+)\\b`);
1304
+ const assignAt = (i) => {
1305
+ const line = lines[i];
1306
+ if (!line || line.length > 10_000)
1307
+ return null;
1308
+ return line.match(assignRe);
1309
+ };
1310
+ // The assignment is position-independent relative to the call — nearest-
1311
+ // backward first, then sweep forward, same order as the componentScoped scan.
1312
+ let assignIdx = -1;
1313
+ let varName = null;
1314
+ for (let i = callIdx; i >= 0; i--) {
1315
+ const m = assignAt(i);
1316
+ if (m) {
1317
+ assignIdx = i;
1318
+ varName = m[1];
1319
+ break;
1320
+ }
1321
+ }
1322
+ if (varName === null) {
1323
+ for (let i = callIdx + 1; i < lines.length; i++) {
1324
+ const m = assignAt(i);
1325
+ if (m) {
1326
+ assignIdx = i;
1327
+ varName = m[1];
1328
+ break;
1329
+ }
1330
+ }
1331
+ }
1332
+ if (varName === null)
1333
+ return null;
1334
+ const varPatterns = localReceiverTypePatterns('php', varName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
1335
+ for (let i = assignIdx; i >= 0; i--) {
1336
+ const line = lines[i];
1337
+ if (line && line.length <= 10_000) {
1338
+ for (const re of varPatterns) {
1339
+ const m = line.match(re);
1340
+ if (m && m[1]) {
1341
+ const type = normalizeInferredTypeName(m[1]);
1342
+ if (type)
1343
+ return type;
1344
+ }
1345
+ }
1346
+ }
1347
+ if (line && /\bfunction\b/.test(line))
1348
+ break;
1349
+ }
1350
+ return null;
1351
+ }
883
1352
  /**
884
1353
  * Try to resolve by method name on a class/object
885
1354
  */
@@ -895,15 +1364,60 @@ function matchMethodCall(ref, context) {
895
1364
  // `Guard.Against.X()`) matched no pattern and never resolved.
896
1365
  const dotMatch = ref.referenceName.match(/^([\w.]+)\.(\w+:?(?:\w+:)*)$/);
897
1366
  const colonMatch = ref.referenceName.match(/^(\w+)::(\w+)$/);
898
- const match = dotMatch || colonMatch;
1367
+ // Lua/Luau method calls use a single colon (`lg:log`); R uses `$` (`lg$log`).
1368
+ // Recognize these receiver/method separators so local-variable receiver-type
1369
+ // inference (#1108) applies to them too — extraction already emits the ref in
1370
+ // this shape, but the resolver otherwise only understood `.` and `::`.
1371
+ const luaColonMatch = (ref.language === 'lua' || ref.language === 'luau')
1372
+ ? ref.referenceName.match(/^([\w.]+):(\w+)$/)
1373
+ : null;
1374
+ const rDollarMatch = ref.language === 'r'
1375
+ ? ref.referenceName.match(/^([\w.]+)\$(\w+)$/)
1376
+ : null;
1377
+ // PHP property receiver: `$this->prop->method()` reaches the resolver as
1378
+ // `this->prop.method` (the extractor records the receiver's raw text with the
1379
+ // leading `$` stripped). Resolve it EXCLUSIVELY through declared-type
1380
+ // inference + resolveMethodOnType validation — the name-similarity strategies
1381
+ // below must never see this shape, so a property whose type can't be
1382
+ // recovered stays unlinked rather than guessed (a wrong inference produces no
1383
+ // edge rather than a wrong one). Deeper chains (`this->a->b.method`) don't
1384
+ // match the single-property pattern and stay unlinked, same as before.
1385
+ const phpThisPropMatch = ref.language === 'php'
1386
+ ? ref.referenceName.match(/^(this->\w+)\.(\w+)$/)
1387
+ : null;
1388
+ if (phpThisPropMatch) {
1389
+ const [, receiver, phpMethodName] = phpThisPropMatch;
1390
+ const inferredType = inferLocalReceiverType(receiver, ref, context);
1391
+ if (!inferredType)
1392
+ return null;
1393
+ return resolveMethodOnType(inferredType, phpMethodName, ref, context, 0.9, 'instance-method', importedFqnOf(inferredType, ref, context));
1394
+ }
1395
+ const match = dotMatch || colonMatch || luaColonMatch || rDollarMatch;
899
1396
  if (!match) {
900
1397
  return null;
901
1398
  }
902
1399
  const [, objectOrClass, methodName] = match;
903
- if (ref.language === 'cpp' && dotMatch) {
904
- const inferredType = inferCppReceiverType(objectOrClass, ref, context);
1400
+ // A simple `receiver.method` / `receiver:method` / `receiver$method` shape whose
1401
+ // receiver type we can try to infer from its local declaration.
1402
+ const inferableReceiver = dotMatch || luaColonMatch || rDollarMatch;
1403
+ // Infer the receiver's type from its local declaration/initializer in the
1404
+ // enclosing scope, then resolve the method on that type (#1108). C++ keeps its
1405
+ // dedicated inferrer (header scan + `auto`); every other language uses the
1406
+ // shared source-based inferrer. resolveMethodOnType validates the method
1407
+ // exists on the inferred type, so a mis-inference produces no edge.
1408
+ if (inferableReceiver) {
1409
+ const inferredType = ref.language === 'cpp'
1410
+ ? inferCppReceiverType(objectOrClass, ref, context)
1411
+ : inferLocalReceiverType(objectOrClass, ref, context);
905
1412
  if (inferredType) {
906
- const typedMatch = resolveMethodOnType(inferredType, methodName, ref, context, 0.9, 'instance-method');
1413
+ // Java/Kotlin: when two classes share the simple name, the file's import
1414
+ // pins WHICH one (#314). Other languages disambiguate by call-site file.
1415
+ const importedFqn = ref.language === 'java' || ref.language === 'kotlin'
1416
+ ? context
1417
+ .getImportMappings(ref.filePath, ref.language)
1418
+ .find((i) => i.localName === inferredType)?.source
1419
+ : undefined;
1420
+ const typedMatch = resolveMethodOnType(inferredType, methodName, ref, context, 0.9, 'instance-method', importedFqn);
907
1421
  if (typedMatch) {
908
1422
  return typedMatch;
909
1423
  }
@@ -928,8 +1442,12 @@ function matchMethodCall(ref, context) {
928
1442
  }
929
1443
  }
930
1444
  }
931
- // Strategy 1: Direct class name match (existing logic)
932
- const classCandidates = context.getNodesByName(objectOrClass);
1445
+ // Strategy 1: Direct class name match (existing logic). When the receiver
1446
+ // names a class that exists in several files (`Logger.log()` / `Logger::log()`
1447
+ // with a `Logger` in both `a/` and `b/`), try the class in the call site's
1448
+ // own file first — otherwise the first-indexed class wins and a call in `b/`
1449
+ // resolves to `a/`'s method (#1079).
1450
+ const classCandidates = preferCallSiteFile(context.getNodesByName(objectOrClass), ref.filePath);
933
1451
  for (const classNode of classCandidates) {
934
1452
  if (classNode.kind === 'class' || classNode.kind === 'struct' || classNode.kind === 'interface') {
935
1453
  // Skip cross-language class matches
@@ -953,7 +1471,7 @@ function matchMethodCall(ref, context) {
953
1471
  // e.g., "permissionEngine" → look for classes containing "PermissionEngine"
954
1472
  const capitalizedReceiver = objectOrClass.charAt(0).toUpperCase() + objectOrClass.slice(1);
955
1473
  if (capitalizedReceiver !== objectOrClass) {
956
- const fuzzyClassCandidates = context.getNodesByName(capitalizedReceiver);
1474
+ const fuzzyClassCandidates = preferCallSiteFile(context.getNodesByName(capitalizedReceiver), ref.filePath);
957
1475
  for (const classNode of fuzzyClassCandidates) {
958
1476
  if (classNode.kind === 'class' || classNode.kind === 'struct' || classNode.kind === 'interface') {
959
1477
  // Skip cross-language class matches
@@ -1006,7 +1524,10 @@ function matchMethodCall(ref, context) {
1006
1524
  const receiverWords = splitCamelCase(objectOrClass);
1007
1525
  let bestMatch;
1008
1526
  let bestScore = 0;
1009
- for (const method of targetMethods) {
1527
+ // Same-file candidates first, so a score tie (`score > bestScore` keeps
1528
+ // the first seen) resolves to the call site's own file rather than the
1529
+ // first-indexed duplicate (#1079).
1530
+ for (const method of preferCallSiteFile(targetMethods, ref.filePath)) {
1010
1531
  const classWords = splitCamelCase(method.qualifiedName);
1011
1532
  let score = receiverWords.filter(w => classWords.some(cw => cw.toLowerCase() === w.toLowerCase())).length;
1012
1533
  // Bonus for same language
@@ -1185,6 +1706,8 @@ function matchFuzzy(ref, context) {
1185
1706
  /**
1186
1707
  * Match all strategies in order of confidence
1187
1708
  */
1709
+ /** ArkUI attribute-helper decorators a `.attr(...)` chain may resolve to. */
1710
+ const ARKUI_ATTRIBUTE_DECORATORS = new Set(['Extend', 'Styles', 'AnimatableExtend', 'Builder']);
1188
1711
  function matchReference(ref, context) {
1189
1712
  // Function-as-value refs (#756) resolve ONLY through the dedicated matcher —
1190
1713
  // never the fuzzy/qualified fallthrough below (a wrong callback edge is
@@ -1192,6 +1715,57 @@ function matchReference(ref, context) {
1192
1715
  if (ref.referenceKind === 'function_ref') {
1193
1716
  return matchFunctionRef(ref, context);
1194
1717
  }
1718
+ // ArkTS chained UI attributes — emitted with a leading dot (`.titleStyle`,
1719
+ // `.width`) by the extractor — resolve ONLY to decorator-marked attribute
1720
+ // helpers: `@Extend`/`@Styles`/`@AnimatableExtend` functions (and global
1721
+ // `@Builder`s used attribute-position). Framework attributes (`.width`,
1722
+ // `.fontSize` — on nearly every UI line) match no such helper and stay
1723
+ // unresolved, NEVER falling through to bare-name matching: on a samples
1724
+ // monorepo that fallthrough manufactured 36k wrong edges, giving single
1725
+ // same-named properties thousands of false callers. Ambiguity rule matches
1726
+ // the rest of the file: several same-named helpers → prefer the call-site
1727
+ // file, still ambiguous → drop the ref rather than guess.
1728
+ if (ref.language === 'arkts' && ref.referenceName.startsWith('.')) {
1729
+ const base = ref.referenceName.slice(1);
1730
+ const candidates = context
1731
+ .getNodesByName(base)
1732
+ .filter((n) => n.language === 'arkts' &&
1733
+ n.kind === 'function' &&
1734
+ (n.decorators ?? []).some((d) => ARKUI_ATTRIBUTE_DECORATORS.has(d)));
1735
+ const chosen = candidates.length > 1 ? preferCallSiteFile(candidates, ref.filePath) : candidates;
1736
+ if (chosen.length !== 1)
1737
+ return null;
1738
+ return {
1739
+ original: ref,
1740
+ targetNodeId: chosen[0].id,
1741
+ confidence: 0.85,
1742
+ resolvedBy: 'exact-match',
1743
+ };
1744
+ }
1745
+ // Erlang `-behaviour(m)` refs target a MODULE. Letting them fall through to
1746
+ // bare-name matching grabs any same-named symbol — on emqx,
1747
+ // `-behaviour(supervisor)` resolved to a `-define(supervisor, …)` macro
1748
+ // constant in an unrelated app. Resolve only to the behaviour module's
1749
+ // namespace; an out-of-repo behaviour (OTP's gen_server/supervisor) stays
1750
+ // unresolved rather than guessed. The same module-only rule applies to every
1751
+ // ref an `.app`/`.app.src` resource file emits — its `{mod, …}` callback and
1752
+ // `{applications, …}` dependency names can only mean modules, and on emqx
1753
+ // the `ssl` OTP app otherwise resolved to a test helper FUNCTION named ssl.
1754
+ if (ref.language === 'erlang' &&
1755
+ (ref.referenceKind === 'implements' || /\.app(?:\.src)?$/i.test(ref.filePath))) {
1756
+ const modules = context
1757
+ .getNodesByName(ref.referenceName)
1758
+ .filter((n) => n.language === 'erlang' && n.kind === 'namespace');
1759
+ const chosen = preferCallSiteFile(modules, ref.filePath)[0];
1760
+ if (!chosen)
1761
+ return null;
1762
+ return {
1763
+ original: ref,
1764
+ targetNodeId: chosen.id,
1765
+ confidence: 0.9,
1766
+ resolvedBy: 'exact-match',
1767
+ };
1768
+ }
1195
1769
  // Try strategies in order of confidence
1196
1770
  let result;
1197
1771
  // 0. File path match (e.g., "snippets/drawer-menu.liquid" → file node)