@lzehrung/codegraph 2.3.30 → 2.4.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 (416) hide show
  1. package/README.md +30 -137
  2. package/codegraph-skill/codegraph/SKILL.md +5 -3
  3. package/dist/agent/artifact.d.ts +2 -0
  4. package/dist/agent/artifact.d.ts.map +1 -1
  5. package/dist/agent/artifact.js.map +1 -1
  6. package/dist/agent/search.d.ts.map +1 -1
  7. package/dist/agent/search.js +3 -0
  8. package/dist/agent/search.js.map +1 -1
  9. package/dist/agent/session.d.ts +3 -0
  10. package/dist/agent/session.d.ts.map +1 -1
  11. package/dist/agent/session.js +10 -2
  12. package/dist/agent/session.js.map +1 -1
  13. package/dist/bin/cli.js +42229 -28876
  14. package/dist/bin/query-index-worker.js +73 -11
  15. package/dist/cli/affected.d.ts.map +1 -1
  16. package/dist/cli/affected.js +4 -1
  17. package/dist/cli/affected.js.map +1 -1
  18. package/dist/cli/command-catalog.js +1 -1
  19. package/dist/cli/command-catalog.js.map +1 -1
  20. package/dist/cli/graph-queries.d.ts.map +1 -1
  21. package/dist/cli/graph-queries.js +27 -1
  22. package/dist/cli/graph-queries.js.map +1 -1
  23. package/dist/cli/help.d.ts +2 -2
  24. package/dist/cli/help.d.ts.map +1 -1
  25. package/dist/cli/help.js +4 -2
  26. package/dist/cli/help.js.map +1 -1
  27. package/dist/cli/options.js +2 -2
  28. package/dist/cli/options.js.map +1 -1
  29. package/dist/drift/artifact.d.ts.map +1 -1
  30. package/dist/drift/artifact.js +15 -18
  31. package/dist/drift/artifact.js.map +1 -1
  32. package/dist/drift/compare.js +1 -1
  33. package/dist/drift/compare.js.map +1 -1
  34. package/dist/drift/snapshot.d.ts.map +1 -1
  35. package/dist/drift/snapshot.js +5 -6
  36. package/dist/drift/snapshot.js.map +1 -1
  37. package/dist/drift/types.d.ts +2 -0
  38. package/dist/drift/types.d.ts.map +1 -1
  39. package/dist/drift/types.js.map +1 -1
  40. package/dist/graph-builder.d.ts.map +1 -1
  41. package/dist/graph-builder.js +4 -6
  42. package/dist/graph-builder.js.map +1 -1
  43. package/dist/graph-edge-collector.d.ts +3 -0
  44. package/dist/graph-edge-collector.d.ts.map +1 -1
  45. package/dist/graph-edge-collector.js +8 -5
  46. package/dist/graph-edge-collector.js.map +1 -1
  47. package/dist/graphs/angularjs.d.ts.map +1 -1
  48. package/dist/graphs/angularjs.js +2 -1
  49. package/dist/graphs/angularjs.js.map +1 -1
  50. package/dist/graphs/edge-resolution.d.ts +4 -1
  51. package/dist/graphs/edge-resolution.d.ts.map +1 -1
  52. package/dist/graphs/edge-resolution.js +26 -2
  53. package/dist/graphs/edge-resolution.js.map +1 -1
  54. package/dist/graphs/specifiers.d.ts.map +1 -1
  55. package/dist/graphs/specifiers.js +6 -2
  56. package/dist/graphs/specifiers.js.map +1 -1
  57. package/dist/graphs/symbol-graph-detailed/ast.d.ts +20 -0
  58. package/dist/graphs/symbol-graph-detailed/ast.d.ts.map +1 -1
  59. package/dist/graphs/symbol-graph-detailed/ast.js +154 -15
  60. package/dist/graphs/symbol-graph-detailed/ast.js.map +1 -1
  61. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts +51 -8
  62. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
  63. package/dist/graphs/symbol-graph-detailed/edge-passes.js +823 -132
  64. package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
  65. package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts +2 -1
  66. package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts.map +1 -1
  67. package/dist/graphs/symbol-graph-detailed/import-aliases.js +139 -7
  68. package/dist/graphs/symbol-graph-detailed/import-aliases.js.map +1 -1
  69. package/dist/graphs/symbol-graph-detailed/member-chains.d.ts +1 -0
  70. package/dist/graphs/symbol-graph-detailed/member-chains.d.ts.map +1 -1
  71. package/dist/graphs/symbol-graph-detailed/member-chains.js +3 -1
  72. package/dist/graphs/symbol-graph-detailed/member-chains.js.map +1 -1
  73. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +128 -22
  74. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
  75. package/dist/graphs/symbol-graph-detailed/receiver-calls.js +872 -125
  76. package/dist/graphs/symbol-graph-detailed/receiver-calls.js.map +1 -1
  77. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  78. package/dist/graphs/symbol-graph-detailed.js +434 -40
  79. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  80. package/dist/graphs/symbol-graph.d.ts +2 -0
  81. package/dist/graphs/symbol-graph.d.ts.map +1 -1
  82. package/dist/graphs/symbol-graph.js +34 -16
  83. package/dist/graphs/symbol-graph.js.map +1 -1
  84. package/dist/impact/call-compatibility/providers/index.d.ts +12 -0
  85. package/dist/impact/call-compatibility/providers/index.d.ts.map +1 -1
  86. package/dist/impact/call-compatibility/providers/index.js +16 -22
  87. package/dist/impact/call-compatibility/providers/index.js.map +1 -1
  88. package/dist/impact/call-compatibility/providers/types.d.ts +2 -0
  89. package/dist/impact/call-compatibility/providers/types.d.ts.map +1 -1
  90. package/dist/impact/call-compatibility/types.d.ts +6 -0
  91. package/dist/impact/call-compatibility/types.d.ts.map +1 -1
  92. package/dist/impact/call-compatibility.d.ts.map +1 -1
  93. package/dist/impact/call-compatibility.js +316 -552
  94. package/dist/impact/call-compatibility.js.map +1 -1
  95. package/dist/impact/map.js +1 -0
  96. package/dist/impact/map.js.map +1 -1
  97. package/dist/impact/member-resolution-coverage.d.ts.map +1 -1
  98. package/dist/impact/member-resolution-coverage.js +1 -1
  99. package/dist/impact/member-resolution-coverage.js.map +1 -1
  100. package/dist/impact/reference-cache.d.ts.map +1 -1
  101. package/dist/impact/reference-cache.js +2 -2
  102. package/dist/impact/reference-cache.js.map +1 -1
  103. package/dist/index.d.ts +1 -1
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +1 -1
  106. package/dist/index.js.map +1 -1
  107. package/dist/indexer/ambiguous-resolution.d.ts +11 -0
  108. package/dist/indexer/ambiguous-resolution.d.ts.map +1 -0
  109. package/dist/indexer/ambiguous-resolution.js +19 -0
  110. package/dist/indexer/ambiguous-resolution.js.map +1 -0
  111. package/dist/indexer/build-cache/module-cache.d.ts +38 -0
  112. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  113. package/dist/indexer/build-cache/module-cache.js +151 -9
  114. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  115. package/dist/indexer/build-cache/options.d.ts +16 -43
  116. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  117. package/dist/indexer/build-cache/options.js +16 -43
  118. package/dist/indexer/build-cache/options.js.map +1 -1
  119. package/dist/indexer/build-cache/project-snapshot.d.ts +1 -0
  120. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  121. package/dist/indexer/build-cache/project-snapshot.js +117 -24
  122. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  123. package/dist/indexer/build-cache/resolver-environment.d.ts.map +1 -1
  124. package/dist/indexer/build-cache/resolver-environment.js +32 -2
  125. package/dist/indexer/build-cache/resolver-environment.js.map +1 -1
  126. package/dist/indexer/build-cache.d.ts +1 -1
  127. package/dist/indexer/build-cache.d.ts.map +1 -1
  128. package/dist/indexer/build-cache.js +1 -1
  129. package/dist/indexer/build-cache.js.map +1 -1
  130. package/dist/indexer/build-index.d.ts.map +1 -1
  131. package/dist/indexer/build-index.js +593 -22
  132. package/dist/indexer/build-index.js.map +1 -1
  133. package/dist/indexer/call-hierarchy.js +1 -1
  134. package/dist/indexer/call-hierarchy.js.map +1 -1
  135. package/dist/indexer/compilation-units.d.ts +101 -0
  136. package/dist/indexer/compilation-units.d.ts.map +1 -0
  137. package/dist/indexer/compilation-units.js +605 -0
  138. package/dist/indexer/compilation-units.js.map +1 -0
  139. package/dist/indexer/cpp-callables.d.ts +20 -0
  140. package/dist/indexer/cpp-callables.d.ts.map +1 -0
  141. package/dist/indexer/cpp-callables.js +554 -0
  142. package/dist/indexer/cpp-callables.js.map +1 -0
  143. package/dist/indexer/declaration-visibility.d.ts +36 -2
  144. package/dist/indexer/declaration-visibility.d.ts.map +1 -1
  145. package/dist/indexer/declaration-visibility.js +136 -2
  146. package/dist/indexer/declaration-visibility.js.map +1 -1
  147. package/dist/indexer/expand-star-imports.d.ts.map +1 -1
  148. package/dist/indexer/expand-star-imports.js +28 -6
  149. package/dist/indexer/expand-star-imports.js.map +1 -1
  150. package/dist/indexer/import-types.d.ts +37 -0
  151. package/dist/indexer/import-types.d.ts.map +1 -1
  152. package/dist/indexer/import-types.js +24 -1
  153. package/dist/indexer/import-types.js.map +1 -1
  154. package/dist/indexer/imports/binding-ranges.d.ts +1 -1
  155. package/dist/indexer/imports/binding-ranges.d.ts.map +1 -1
  156. package/dist/indexer/imports/context.d.ts +11 -1
  157. package/dist/indexer/imports/context.d.ts.map +1 -1
  158. package/dist/indexer/imports/import-binding-tables.d.ts +75 -0
  159. package/dist/indexer/imports/import-binding-tables.d.ts.map +1 -0
  160. package/dist/indexer/imports/import-binding-tables.js +544 -0
  161. package/dist/indexer/imports/import-binding-tables.js.map +1 -0
  162. package/dist/indexer/imports/js-text-imports.js +4 -4
  163. package/dist/indexer/imports/js-text-imports.js.map +1 -1
  164. package/dist/indexer/imports/language-specific.d.ts +3 -22
  165. package/dist/indexer/imports/language-specific.d.ts.map +1 -1
  166. package/dist/indexer/imports/language-specific.js +29 -362
  167. package/dist/indexer/imports/language-specific.js.map +1 -1
  168. package/dist/indexer/imports/native-captures.d.ts.map +1 -1
  169. package/dist/indexer/imports/native-captures.js +18 -6
  170. package/dist/indexer/imports/native-captures.js.map +1 -1
  171. package/dist/indexer/imports/python.d.ts +10 -2
  172. package/dist/indexer/imports/python.d.ts.map +1 -1
  173. package/dist/indexer/imports/python.js +91 -40
  174. package/dist/indexer/imports/python.js.map +1 -1
  175. package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -1
  176. package/dist/indexer/imports/text-import-extractors.js +51 -12
  177. package/dist/indexer/imports/text-import-extractors.js.map +1 -1
  178. package/dist/indexer/imports.d.ts.map +1 -1
  179. package/dist/indexer/imports.js +25 -5
  180. package/dist/indexer/imports.js.map +1 -1
  181. package/dist/indexer/incremental-plan.d.ts +33 -0
  182. package/dist/indexer/incremental-plan.d.ts.map +1 -1
  183. package/dist/indexer/incremental-plan.js +187 -1
  184. package/dist/indexer/incremental-plan.js.map +1 -1
  185. package/dist/indexer/locals-and-exports.d.ts +2 -0
  186. package/dist/indexer/locals-and-exports.d.ts.map +1 -1
  187. package/dist/indexer/locals-and-exports.js +565 -54
  188. package/dist/indexer/locals-and-exports.js.map +1 -1
  189. package/dist/indexer/name-lookup-policies/c-family.d.ts +7 -0
  190. package/dist/indexer/name-lookup-policies/c-family.d.ts.map +1 -0
  191. package/dist/indexer/name-lookup-policies/c-family.js +117 -0
  192. package/dist/indexer/name-lookup-policies/c-family.js.map +1 -0
  193. package/dist/indexer/name-lookup-policies/csharp-using-static.d.ts +11 -0
  194. package/dist/indexer/name-lookup-policies/csharp-using-static.d.ts.map +1 -0
  195. package/dist/indexer/name-lookup-policies/csharp-using-static.js +136 -0
  196. package/dist/indexer/name-lookup-policies/csharp-using-static.js.map +1 -0
  197. package/dist/indexer/name-lookup-policies/implicit-self.d.ts +10 -0
  198. package/dist/indexer/name-lookup-policies/implicit-self.d.ts.map +1 -0
  199. package/dist/indexer/name-lookup-policies/implicit-self.js +113 -0
  200. package/dist/indexer/name-lookup-policies/implicit-self.js.map +1 -0
  201. package/dist/indexer/name-lookup-policies/index.d.ts +3 -0
  202. package/dist/indexer/name-lookup-policies/index.d.ts.map +1 -0
  203. package/dist/indexer/name-lookup-policies/index.js +106 -0
  204. package/dist/indexer/name-lookup-policies/index.js.map +1 -0
  205. package/dist/indexer/name-lookup-policies/php.d.ts +3 -0
  206. package/dist/indexer/name-lookup-policies/php.d.ts.map +1 -0
  207. package/dist/indexer/name-lookup-policies/php.js +75 -0
  208. package/dist/indexer/name-lookup-policies/php.js.map +1 -0
  209. package/dist/indexer/name-resolution-types.d.ts +99 -0
  210. package/dist/indexer/name-resolution-types.d.ts.map +1 -0
  211. package/dist/indexer/name-resolution-types.js +2 -0
  212. package/dist/indexer/name-resolution-types.js.map +1 -0
  213. package/dist/indexer/name-resolution.d.ts +52 -0
  214. package/dist/indexer/name-resolution.d.ts.map +1 -0
  215. package/dist/indexer/name-resolution.js +189 -0
  216. package/dist/indexer/name-resolution.js.map +1 -0
  217. package/dist/indexer/navigation-cpp.d.ts +50 -0
  218. package/dist/indexer/navigation-cpp.d.ts.map +1 -0
  219. package/dist/indexer/navigation-cpp.js +654 -0
  220. package/dist/indexer/navigation-cpp.js.map +1 -0
  221. package/dist/indexer/navigation-goto.d.ts +107 -4
  222. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  223. package/dist/indexer/navigation-goto.js +2075 -137
  224. package/dist/indexer/navigation-goto.js.map +1 -1
  225. package/dist/indexer/navigation-local.d.ts +18 -2
  226. package/dist/indexer/navigation-local.d.ts.map +1 -1
  227. package/dist/indexer/navigation-local.js +498 -61
  228. package/dist/indexer/navigation-local.js.map +1 -1
  229. package/dist/indexer/navigation-php.d.ts +66 -0
  230. package/dist/indexer/navigation-php.d.ts.map +1 -1
  231. package/dist/indexer/navigation-php.js +287 -4
  232. package/dist/indexer/navigation-php.js.map +1 -1
  233. package/dist/indexer/navigation-references.d.ts +72 -5
  234. package/dist/indexer/navigation-references.d.ts.map +1 -1
  235. package/dist/indexer/navigation-references.js +620 -54
  236. package/dist/indexer/navigation-references.js.map +1 -1
  237. package/dist/indexer/navigation-resolve.d.ts +33 -2
  238. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  239. package/dist/indexer/navigation-resolve.js +446 -193
  240. package/dist/indexer/navigation-resolve.js.map +1 -1
  241. package/dist/indexer/navigation.d.ts +28 -2
  242. package/dist/indexer/navigation.d.ts.map +1 -1
  243. package/dist/indexer/navigation.js +1082 -151
  244. package/dist/indexer/navigation.js.map +1 -1
  245. package/dist/indexer/php-namespace-symbols.d.ts +66 -0
  246. package/dist/indexer/php-namespace-symbols.d.ts.map +1 -0
  247. package/dist/indexer/php-namespace-symbols.js +342 -0
  248. package/dist/indexer/php-namespace-symbols.js.map +1 -0
  249. package/dist/indexer/reference-context.d.ts +2 -0
  250. package/dist/indexer/reference-context.d.ts.map +1 -1
  251. package/dist/indexer/reference-context.js +4 -0
  252. package/dist/indexer/reference-context.js.map +1 -1
  253. package/dist/indexer/scope-nodes.d.ts +92 -13
  254. package/dist/indexer/scope-nodes.d.ts.map +1 -1
  255. package/dist/indexer/scope-nodes.js +212 -20
  256. package/dist/indexer/scope-nodes.js.map +1 -1
  257. package/dist/indexer/scope-types.d.ts +25 -1
  258. package/dist/indexer/scope-types.d.ts.map +1 -1
  259. package/dist/indexer/scope.d.ts.map +1 -1
  260. package/dist/indexer/scope.js +894 -45
  261. package/dist/indexer/scope.js.map +1 -1
  262. package/dist/indexer/shared-owner-identity.d.ts +53 -0
  263. package/dist/indexer/shared-owner-identity.d.ts.map +1 -0
  264. package/dist/indexer/shared-owner-identity.js +460 -0
  265. package/dist/indexer/shared-owner-identity.js.map +1 -0
  266. package/dist/indexer/shared.d.ts +1 -1
  267. package/dist/indexer/shared.d.ts.map +1 -1
  268. package/dist/indexer/shared.js +1 -1
  269. package/dist/indexer/shared.js.map +1 -1
  270. package/dist/indexer/star-import-precedence.d.ts +114 -0
  271. package/dist/indexer/star-import-precedence.d.ts.map +1 -0
  272. package/dist/indexer/star-import-precedence.js +396 -0
  273. package/dist/indexer/star-import-precedence.js.map +1 -0
  274. package/dist/indexer/symbols.d.ts +3 -1
  275. package/dist/indexer/symbols.d.ts.map +1 -1
  276. package/dist/indexer/symbols.js +58 -18
  277. package/dist/indexer/symbols.js.map +1 -1
  278. package/dist/indexer/ts-callables.d.ts +51 -0
  279. package/dist/indexer/ts-callables.d.ts.map +1 -0
  280. package/dist/indexer/ts-callables.js +264 -0
  281. package/dist/indexer/ts-callables.js.map +1 -0
  282. package/dist/indexer/types.d.ts +23 -1
  283. package/dist/indexer/types.d.ts.map +1 -1
  284. package/dist/indexer/unused-exports.d.ts +13 -0
  285. package/dist/indexer/unused-exports.d.ts.map +1 -0
  286. package/dist/indexer/unused-exports.js +159 -0
  287. package/dist/indexer/unused-exports.js.map +1 -0
  288. package/dist/indexer/workspace-symbols.d.ts.map +1 -1
  289. package/dist/indexer/workspace-symbols.js +3 -2
  290. package/dist/indexer/workspace-symbols.js.map +1 -1
  291. package/dist/indexer.d.ts +2 -2
  292. package/dist/indexer.d.ts.map +1 -1
  293. package/dist/indexer.js +1 -1
  294. package/dist/indexer.js.map +1 -1
  295. package/dist/languages/callable-arity.d.ts +202 -0
  296. package/dist/languages/callable-arity.d.ts.map +1 -0
  297. package/dist/languages/callable-arity.js +1182 -0
  298. package/dist/languages/callable-arity.js.map +1 -0
  299. package/dist/languages/definitions/c-family.d.ts.map +1 -1
  300. package/dist/languages/definitions/c-family.js +30 -1
  301. package/dist/languages/definitions/c-family.js.map +1 -1
  302. package/dist/languages/definitions/c.d.ts +4 -0
  303. package/dist/languages/definitions/c.d.ts.map +1 -1
  304. package/dist/languages/definitions/c.js +19 -0
  305. package/dist/languages/definitions/c.js.map +1 -1
  306. package/dist/languages/definitions/cpp.d.ts.map +1 -1
  307. package/dist/languages/definitions/cpp.js +12 -0
  308. package/dist/languages/definitions/cpp.js.map +1 -1
  309. package/dist/languages/definitions/csharp.d.ts.map +1 -1
  310. package/dist/languages/definitions/csharp.js +2 -8
  311. package/dist/languages/definitions/csharp.js.map +1 -1
  312. package/dist/languages/definitions/go.d.ts.map +1 -1
  313. package/dist/languages/definitions/go.js +3 -0
  314. package/dist/languages/definitions/go.js.map +1 -1
  315. package/dist/languages/definitions/javascript.d.ts.map +1 -1
  316. package/dist/languages/definitions/javascript.js +10 -1
  317. package/dist/languages/definitions/javascript.js.map +1 -1
  318. package/dist/languages/definitions/js-family.d.ts +1 -1
  319. package/dist/languages/definitions/js-family.d.ts.map +1 -1
  320. package/dist/languages/definitions/js-family.js +7 -1
  321. package/dist/languages/definitions/js-family.js.map +1 -1
  322. package/dist/languages/definitions/php.d.ts.map +1 -1
  323. package/dist/languages/definitions/php.js +5 -1
  324. package/dist/languages/definitions/php.js.map +1 -1
  325. package/dist/languages/definitions/typescript.d.ts.map +1 -1
  326. package/dist/languages/definitions/typescript.js +8 -1
  327. package/dist/languages/definitions/typescript.js.map +1 -1
  328. package/dist/languages/definitions/zig.d.ts.map +1 -1
  329. package/dist/languages/definitions/zig.js +2 -0
  330. package/dist/languages/definitions/zig.js.map +1 -1
  331. package/dist/mcp/handlers.js +14 -7
  332. package/dist/mcp/handlers.js.map +1 -1
  333. package/dist/review/candidates.d.ts.map +1 -1
  334. package/dist/review/candidates.js +1 -1
  335. package/dist/review/candidates.js.map +1 -1
  336. package/dist/review/deleted.d.ts +3 -3
  337. package/dist/review/deleted.d.ts.map +1 -1
  338. package/dist/review/deleted.js +82 -32
  339. package/dist/review/deleted.js.map +1 -1
  340. package/dist/review/report.d.ts +1 -0
  341. package/dist/review/report.d.ts.map +1 -1
  342. package/dist/review/report.js +1 -1
  343. package/dist/review/report.js.map +1 -1
  344. package/dist/review.d.ts.map +1 -1
  345. package/dist/review.js +1 -0
  346. package/dist/review.js.map +1 -1
  347. package/dist/sql/navigation.d.ts.map +1 -1
  348. package/dist/sql/navigation.js +1 -0
  349. package/dist/sql/navigation.js.map +1 -1
  350. package/dist/sql/source-graph.d.ts.map +1 -1
  351. package/dist/sql/source-graph.js +2 -2
  352. package/dist/sql/source-graph.js.map +1 -1
  353. package/dist/sqlite/schema.d.ts +1 -1
  354. package/dist/sqlite/schema.d.ts.map +1 -1
  355. package/dist/sqlite/schema.js +8 -2
  356. package/dist/sqlite/schema.js.map +1 -1
  357. package/dist/sqlite/write.js +2 -2
  358. package/dist/sqlite/write.js.map +1 -1
  359. package/dist/types.d.ts +2 -0
  360. package/dist/types.d.ts.map +1 -1
  361. package/dist/util/bloom-filter.d.ts +7 -1
  362. package/dist/util/bloom-filter.d.ts.map +1 -1
  363. package/dist/util/bloom-filter.js +12 -2
  364. package/dist/util/bloom-filter.js.map +1 -1
  365. package/dist/util/dynamic-import-tables.d.ts +88 -0
  366. package/dist/util/dynamic-import-tables.d.ts.map +1 -0
  367. package/dist/util/dynamic-import-tables.js +100 -0
  368. package/dist/util/dynamic-import-tables.js.map +1 -0
  369. package/dist/util/graph-edges.d.ts +19 -1
  370. package/dist/util/graph-edges.d.ts.map +1 -1
  371. package/dist/util/graph-edges.js +30 -4
  372. package/dist/util/graph-edges.js.map +1 -1
  373. package/dist/util/identifiers.d.ts +15 -0
  374. package/dist/util/identifiers.d.ts.map +1 -1
  375. package/dist/util/identifiers.js +35 -0
  376. package/dist/util/identifiers.js.map +1 -1
  377. package/dist/util/member-access-tables.d.ts +129 -0
  378. package/dist/util/member-access-tables.d.ts.map +1 -0
  379. package/dist/util/member-access-tables.js +285 -0
  380. package/dist/util/member-access-tables.js.map +1 -0
  381. package/dist/util/member-access.d.ts +17 -0
  382. package/dist/util/member-access.d.ts.map +1 -1
  383. package/dist/util/member-access.js +138 -93
  384. package/dist/util/member-access.js.map +1 -1
  385. package/dist/util/resolution/cargo-targets.d.ts +11 -0
  386. package/dist/util/resolution/cargo-targets.d.ts.map +1 -1
  387. package/dist/util/resolution/cargo-targets.js +174 -13
  388. package/dist/util/resolution/cargo-targets.js.map +1 -1
  389. package/dist/util/resolution/csharp.d.ts +33 -1
  390. package/dist/util/resolution/csharp.d.ts.map +1 -1
  391. package/dist/util/resolution/csharp.js +145 -30
  392. package/dist/util/resolution/csharp.js.map +1 -1
  393. package/dist/util/resolution/php.d.ts.map +1 -1
  394. package/dist/util/resolution/php.js +35 -8
  395. package/dist/util/resolution/php.js.map +1 -1
  396. package/dist/util/resolution/python.d.ts +9 -0
  397. package/dist/util/resolution/python.d.ts.map +1 -1
  398. package/dist/util/resolution/python.js +46 -0
  399. package/dist/util/resolution/python.js.map +1 -1
  400. package/dist/util/resolution/rust.d.ts.map +1 -1
  401. package/dist/util/resolution/rust.js +95 -26
  402. package/dist/util/resolution/rust.js.map +1 -1
  403. package/dist/util/resolution-candidates.d.ts +5 -0
  404. package/dist/util/resolution-candidates.d.ts.map +1 -1
  405. package/dist/util/resolution-candidates.js +16 -3
  406. package/dist/util/resolution-candidates.js.map +1 -1
  407. package/dist/util/resolution.d.ts +2 -1
  408. package/dist/util/resolution.d.ts.map +1 -1
  409. package/dist/util/resolution.js +96 -5
  410. package/dist/util/resolution.js.map +1 -1
  411. package/dist/util/specifiers.d.ts +20 -0
  412. package/dist/util/specifiers.d.ts.map +1 -1
  413. package/dist/util/specifiers.js +39 -93
  414. package/dist/util/specifiers.js.map +1 -1
  415. package/docs/mcp.md +3 -2
  416. package/package.json +3 -3
@@ -1,15 +1,17 @@
1
1
  import path from "node:path";
2
- import { findUsageReferences, goToDefinition } from "../indexer/navigation.js";
2
+ import { findUsageReferences, getCppEquivalentCallableDefinitions, goToDefinition } from "../indexer/navigation.js";
3
3
  import { ensureParsedContext } from "../indexer/parse-context.js";
4
+ import { findClosestScopeBinding, getOrBuildScopeIndex, resolveNamedDefinition } from "../indexer/navigation-local.js";
5
+ import { cppCallableShapeForNode, cppCallableIsDefinition, cppEquivalentCallableBindings, } from "../indexer/cpp-callables.js";
6
+ import { getCachedReferenceCandidateFiles } from "../indexer/navigation-references.js";
4
7
  import { SymbolKind } from "../indexer/types.js";
5
8
  import { supportForFileWithoutHeaderSample } from "../languages.js";
6
- import { isJsTsLanguage } from "../languages/js-family.js";
9
+ import { CALLABLE_DECLARATION_NODE_TYPES, CALLABLE_VARIABLE_VALUE_NODE_TYPES, getCallableArity, getCallableArityFromParameterText, getCallableDeclarationKind, getCallArgumentCount, getCallArgumentCountFromArgumentText, memberLookupBinding, } from "../languages/callable-arity.js";
7
10
  import { sliceText, toRange } from "../util/ast.js";
8
11
  import { fileIdentityKey } from "../util/paths.js";
9
- import { getCallCompatibilityProvider, getCallCompatibilitySupportedLanguages, registerCallCompatibilityExtractors, } from "./call-compatibility/providers/index.js";
10
- import { findOpeningParen, findSignatureOpeningParen, findCommentEnd, findCallOpeningParen, findBalancedParentheses, canStartRegexLiteral, findRegexLiteralEnd, splitTopLevelCommaGroups, } from "./call-compatibility/text-scanner.js";
11
- import { PARAMETER_LIST_NODE_TYPES } from "../graphs/symbol-graph-detailed/receiver-calls.js";
12
- import { directSignatureParameterNode, findAncestorOfTypes, findFirstDescendantOfTypes, } from "./signature-node-utils.js";
12
+ import { getCallCompatibilityLanguageProfile, getCallCompatibilityProvider, getCallCompatibilitySupportedLanguages, registerCallCompatibilityExtractors, } from "./call-compatibility/providers/index.js";
13
+ import { findSignatureOpeningParen, findCallOpeningParen, findBalancedParentheses, } from "./call-compatibility/text-scanner.js";
14
+ import { findAncestorOfTypes } from "./signature-node-utils.js";
13
15
  import { canStartReferenceLookup, recordReferenceLookupOmitted, recordReferenceLookupStarted, } from "./budgets.js";
14
16
  function supportsCallCompatibilityLanguage(languageId) {
15
17
  return getCallCompatibilityProvider(languageId) !== null;
@@ -17,391 +19,33 @@ function supportsCallCompatibilityLanguage(languageId) {
17
19
  function referenceScanLimitForCallsites(maxRefs) {
18
20
  return Math.max(maxRefs + 50, maxRefs * 4);
19
21
  }
20
- function hasTopLevelEquals(text) {
21
- let parenDepth = 0;
22
- let bracketDepth = 0;
23
- let braceDepth = 0;
24
- let angleDepth = 0;
25
- let quote = null;
26
- let escaped = false;
27
- for (let index = 0; index < text.length; index += 1) {
28
- const char = text[index];
29
- if (quote) {
30
- if (escaped) {
31
- escaped = false;
32
- continue;
33
- }
34
- if (char === "\\") {
35
- escaped = true;
36
- continue;
37
- }
38
- if (char === quote) {
39
- quote = null;
40
- }
41
- continue;
42
- }
43
- const commentEnd = findCommentEnd(text, index);
44
- if (commentEnd !== null) {
45
- if (commentEnd < 0) {
46
- return false;
47
- }
48
- index = commentEnd - 1;
49
- continue;
50
- }
51
- if (char === '"' || char === "'" || char === "`") {
52
- quote = char;
53
- continue;
54
- }
55
- if (char === "(") {
56
- parenDepth += 1;
57
- continue;
58
- }
59
- if (char === ")") {
60
- parenDepth -= 1;
61
- if (parenDepth < 0) {
62
- return false;
63
- }
64
- continue;
65
- }
66
- if (char === "[") {
67
- bracketDepth += 1;
68
- continue;
69
- }
70
- if (char === "]") {
71
- bracketDepth -= 1;
72
- if (bracketDepth < 0) {
73
- return false;
74
- }
75
- continue;
76
- }
77
- if (char === "{") {
78
- braceDepth += 1;
79
- continue;
80
- }
81
- if (char === "}") {
82
- braceDepth -= 1;
83
- if (braceDepth < 0) {
84
- return false;
85
- }
86
- continue;
87
- }
88
- const atTopLevel = !parenDepth && !bracketDepth && !braceDepth;
89
- if (char === "<" && atTopLevel) {
90
- angleDepth += 1;
91
- continue;
92
- }
93
- if (char === ">" && text[index - 1] !== "=" && atTopLevel && angleDepth) {
94
- angleDepth -= 1;
95
- continue;
96
- }
97
- if (char === "=" && text[index + 1] !== ">" && atTopLevel && !angleDepth) {
98
- return true;
99
- }
100
- }
101
- return false;
102
- }
103
- function isOptionalParameter(parameter) {
104
- const colonIndex = parameter.indexOf(":");
105
- let searchText = parameter;
106
- if (colonIndex >= 0) {
107
- searchText = parameter.slice(0, colonIndex);
108
- }
109
- return searchText.includes("?") || hasTopLevelEquals(parameter);
110
- }
111
- function isThisParameter(parameter) {
112
- const colonIndex = parameter.indexOf(":");
113
- if (colonIndex < 0) {
114
- return parameter.trim() === "this";
115
- }
116
- return parameter.slice(0, colonIndex).trim() === "this";
117
- }
118
- const callableDeclarationTypes = new Set([
119
- "function_declaration",
120
- "function_definition",
121
- "function_item",
122
- "method",
123
- "singleton_method",
124
- "method_declaration",
125
- "constructor_declaration",
126
- "init_declaration",
127
- "protocol_function_declaration",
128
- "arrow_function",
129
- "function",
130
- "function_expression",
131
- "variable_declarator",
132
- "declaration",
133
- ]);
134
- const callableVariableValueTypes = new Set(["arrow_function", "function_expression", "function"]);
135
- const parameterListTypes = new Set(Object.keys(PARAMETER_LIST_NODE_TYPES));
136
- function isPythonMethodDeclaration(declaration) {
137
- let current = declaration.parent;
138
- while (current) {
139
- if (current.type === "class_definition") {
140
- return true;
141
- }
142
- if (current.type === "function_definition") {
143
- return false;
144
- }
145
- current = current.parent;
146
- }
147
- return false;
148
- }
149
- function shouldSkipFirstReceiverParameter(languageId, declaration) {
150
- if (languageId === "python") {
151
- return isPythonMethodDeclaration(declaration);
152
- }
153
- return true;
154
- }
155
- function findSignatureParameterText(request) {
156
- if (!request.tree) {
157
- return null;
158
- }
159
- const node = request.tree.rootNode.descendantForIndex(request.symbolStartIndex, request.symbolStartIndex);
160
- const declaration = findAncestorOfTypes(node, callableDeclarationTypes);
161
- if (!declaration) {
162
- return null;
163
- }
164
- let params = directSignatureParameterNode(declaration);
165
- if (!params && declaration.type === "variable_declarator") {
166
- const valueNode = declaration.childForFieldName("value");
167
- if (!valueNode || !callableVariableValueTypes.has(valueNode.type)) {
168
- return null;
169
- }
170
- params = directSignatureParameterNode(valueNode) ?? findFirstDescendantOfTypes(valueNode, parameterListTypes);
171
- }
172
- if (!params) {
173
- params = findFirstDescendantOfTypes(declaration, parameterListTypes);
174
- }
175
- if (!params) {
176
- if (request.languageId === "swift") {
177
- const parameterNodes = declaration.namedChildren.filter((child) => child.type === "parameter");
178
- const first = parameterNodes[0];
179
- const last = parameterNodes[parameterNodes.length - 1];
180
- if (first && last) {
181
- return {
182
- text: request.source.slice(first.startIndex, last.endIndex),
183
- skipFirstReceiver: shouldSkipFirstReceiverParameter(request.languageId, declaration),
184
- };
185
- }
186
- }
187
- return {
188
- text: "",
189
- skipFirstReceiver: shouldSkipFirstReceiverParameter(request.languageId, declaration),
190
- };
191
- }
192
- const text = request.source.slice(params.startIndex, params.endIndex).trim();
193
- if (text.startsWith("(") && text.endsWith(")")) {
194
- return {
195
- text: text.slice(1, -1),
196
- skipFirstReceiver: shouldSkipFirstReceiverParameter(request.languageId, declaration),
197
- };
198
- }
199
- return {
200
- text,
201
- skipFirstReceiver: shouldSkipFirstReceiverParameter(request.languageId, declaration),
202
- };
203
- }
204
- function isReceiverParameter(languageId, parameter, index, skipFirstReceiver) {
205
- if (!skipFirstReceiver) {
206
- return false;
207
- }
208
- const trimmed = parameter.trim();
209
- if (!index && (languageId === "python" || languageId === "ruby")) {
210
- return trimmed === "self" || trimmed === "cls" || trimmed.startsWith("self:") || trimmed.startsWith("cls:");
211
- }
212
- if (!index && languageId === "rust") {
213
- return trimmed === "self" || trimmed === "&self" || trimmed === "&mut self" || trimmed.startsWith("self:");
214
- }
215
- if (isJsTsLanguage(languageId)) {
216
- return isThisParameter(trimmed);
217
- }
218
- return false;
219
- }
220
- function hasTopLevelEllipsis(text) {
221
- let parenDepth = 0;
222
- let bracketDepth = 0;
223
- let braceDepth = 0;
224
- let angleDepth = 0;
225
- let quote = null;
226
- let escaped = false;
227
- for (let index = 0; index < text.length; index += 1) {
228
- const char = text[index];
229
- if (quote) {
230
- if (escaped) {
231
- escaped = false;
232
- continue;
233
- }
234
- if (char === "\\") {
235
- escaped = true;
236
- continue;
237
- }
238
- if (char === quote) {
239
- quote = null;
240
- }
241
- continue;
242
- }
243
- const commentEnd = findCommentEnd(text, index);
244
- if (commentEnd !== null) {
245
- if (commentEnd < 0) {
246
- return false;
247
- }
248
- index = commentEnd - 1;
249
- continue;
250
- }
251
- if (canStartRegexLiteral(text, index, 0)) {
252
- const regexEnd = findRegexLiteralEnd(text, index);
253
- if (regexEnd === null || regexEnd < 0) {
254
- return false;
255
- }
256
- index = regexEnd - 1;
257
- continue;
258
- }
259
- if (char === '"' || char === "'" || char === "`") {
260
- quote = char;
261
- continue;
262
- }
263
- if (char === "(") {
264
- parenDepth += 1;
265
- continue;
266
- }
267
- if (char === ")") {
268
- parenDepth -= 1;
269
- if (parenDepth < 0) {
270
- return false;
271
- }
272
- continue;
273
- }
274
- if (char === "[") {
275
- bracketDepth += 1;
276
- continue;
277
- }
278
- if (char === "]") {
279
- bracketDepth -= 1;
280
- if (bracketDepth < 0) {
281
- return false;
282
- }
283
- continue;
284
- }
285
- if (char === "{") {
286
- braceDepth += 1;
287
- continue;
288
- }
289
- if (char === "}") {
290
- braceDepth -= 1;
291
- if (braceDepth < 0) {
292
- return false;
293
- }
294
- continue;
295
- }
296
- const atDelimiterTopLevel = !parenDepth && !bracketDepth && !braceDepth;
297
- if (char === "<" && atDelimiterTopLevel) {
298
- angleDepth += 1;
299
- continue;
300
- }
301
- if (char === ">" && angleDepth && atDelimiterTopLevel && text[index - 1] !== "=") {
302
- angleDepth -= 1;
303
- continue;
304
- }
305
- if (!angleDepth && atDelimiterTopLevel && text.startsWith("...", index)) {
306
- return true;
307
- }
308
- }
309
- return false;
310
- }
311
- function isParameterSeparator(languageId, parameter) {
312
- const trimmed = parameter.trim();
313
- return languageId === "python" && (trimmed === "/" || trimmed === "*");
314
- }
315
- function isRestParameter(languageId, parameter) {
316
- const trimmed = parameter.trim();
317
- if (!trimmed) {
318
- return false;
319
- }
320
- if (hasTopLevelEllipsis(trimmed)) {
321
- return true;
322
- }
323
- if (languageId === "python" || languageId === "ruby") {
324
- return trimmed.startsWith("*") || trimmed.startsWith("**");
325
- }
326
- if (languageId === "csharp") {
327
- return /\bparams\b/.test(trimmed);
328
- }
329
- if (languageId === "kotlin") {
330
- return /\bvararg\b/.test(trimmed);
331
- }
332
- return false;
333
- }
334
- function isOptionalParameterForLanguage(languageId, parameter) {
335
- const trimmed = parameter.trim();
336
- if (!trimmed) {
337
- return false;
338
- }
339
- if (isJsTsLanguage(languageId)) {
340
- return isOptionalParameter(trimmed);
341
- }
342
- if (languageId === "ruby" && /^[A-Za-z_]\w*:\s*\S/.test(trimmed)) {
343
- return true;
344
- }
345
- return hasTopLevelEquals(trimmed);
346
- }
347
- function parameterSlotCount(languageId, parameter) {
348
- const trimmed = parameter.trim();
349
- if (!trimmed) {
350
- return 0;
351
- }
352
- if ((languageId === "c" || languageId === "cpp") && trimmed === "void") {
353
- return 0;
354
- }
355
- return 1;
356
- }
357
- function signatureFromParameterText(languageId, parameterText, angleMode, skipFirstReceiver = true) {
358
- const parameters = splitTopLevelCommaGroups(parameterText, angleMode, languageId !== "python");
359
- if (!parameters) {
22
+ const callableDeclarationTypes = new Set(Object.keys(CALLABLE_DECLARATION_NODE_TYPES));
23
+ function extractCallableSignatureFromProvider(request) {
24
+ const profile = getCallCompatibilityLanguageProfile(request.languageId);
25
+ if (!profile) {
360
26
  return null;
361
27
  }
362
- let minArgs = 0;
363
- let maxArgs = 0;
364
- let positionalArgCount = 0;
365
- let hasRest = false;
366
- parameters.forEach((parameter, index) => {
367
- const trimmed = parameter.trim();
368
- if (!trimmed ||
369
- isParameterSeparator(languageId, trimmed) ||
370
- isReceiverParameter(languageId, trimmed, index, skipFirstReceiver)) {
371
- return;
372
- }
373
- if (isRestParameter(languageId, trimmed)) {
374
- hasRest = true;
375
- return;
376
- }
377
- if (languageId === "ruby" && /^[A-Za-z_]\w*:/.test(trimmed)) {
378
- maxArgs += 1;
379
- if (!isOptionalParameterForLanguage(languageId, trimmed)) {
380
- minArgs += 1;
28
+ const binding = request.binding ?? "bound";
29
+ if (request.tree) {
30
+ const node = request.tree.rootNode.descendantForIndex(request.symbolStartIndex, request.symbolStartIndex);
31
+ const declaration = findAncestorOfTypes(node, callableDeclarationTypes);
32
+ if (declaration) {
33
+ const arity = getCallableArity({ languageId: request.languageId, source: request.source, declaration, binding });
34
+ if (arity) {
35
+ return { ...arity, confidence: "high" };
36
+ }
37
+ // A tree-proven declaration with no provable parameter structure is unknown, except a
38
+ // variable declarator whose value is not callable: that shape always fell back to the
39
+ // source scan, and the fallback must not change for it.
40
+ const valueNode = declaration.type === "variable_declarator" ? declaration.childForFieldName("value") : null;
41
+ const fallsThroughToSource = declaration.type === "variable_declarator" &&
42
+ (!valueNode || !CALLABLE_VARIABLE_VALUE_NODE_TYPES[valueNode.type]);
43
+ if (!fallsThroughToSource) {
44
+ return null;
381
45
  }
382
- return;
383
- }
384
- const slotCount = parameterSlotCount(languageId, trimmed);
385
- if (!slotCount) {
386
- return;
387
- }
388
- positionalArgCount += slotCount;
389
- maxArgs += slotCount;
390
- if (!isOptionalParameterForLanguage(languageId, trimmed)) {
391
- minArgs = positionalArgCount;
392
46
  }
393
- });
394
- return { minArgs, maxArgs: hasRest ? null : maxArgs, confidence: "high" };
395
- }
396
- function extractCallableSignatureFromProvider(request) {
397
- if (!supportsCallCompatibilityLanguage(request.languageId)) {
398
- return null;
399
47
  }
400
- const astParameterText = findSignatureParameterText(request);
401
- if (astParameterText !== null) {
402
- return signatureFromParameterText(request.languageId, astParameterText.text, "type-context", astParameterText.skipFirstReceiver);
403
- }
404
- if (!isJsTsLanguage(request.languageId)) {
48
+ if (!profile.sourceFallback) {
405
49
  return null;
406
50
  }
407
51
  const openIndex = findSignatureOpeningParen(request.source, request.symbolStartIndex);
@@ -409,17 +53,24 @@ function extractCallableSignatureFromProvider(request) {
409
53
  if (!balanced) {
410
54
  return null;
411
55
  }
412
- return signatureFromParameterText(request.languageId, balanced.inner, "type-context");
56
+ const arity = getCallableArityFromParameterText({
57
+ languageId: request.languageId,
58
+ parameterText: balanced.inner,
59
+ binding,
60
+ });
61
+ return arity ? { ...arity, confidence: "high" } : null;
413
62
  }
414
63
  function extractCallsiteArgumentsFromProvider(request) {
415
- if (!supportsCallCompatibilityLanguage(request.languageId)) {
64
+ const profile = getCallCompatibilityLanguageProfile(request.languageId);
65
+ if (!profile) {
416
66
  return null;
417
67
  }
418
- const astArgumentText = findCallsiteArgumentText(request);
419
- if (astArgumentText !== null) {
420
- return callsiteFromArgumentText(request.languageId, astArgumentText.text, astArgumentText.trailingArgumentCount);
68
+ const callNode = request.tree ? locateCallsiteCallNode(request) : null;
69
+ if (callNode) {
70
+ const argCount = getCallArgumentCount({ languageId: request.languageId, source: request.source, call: callNode });
71
+ return argCount === null ? null : { argCount, confidence: "high" };
421
72
  }
422
- if (!isJsTsLanguage(request.languageId)) {
73
+ if (!profile.sourceFallback) {
423
74
  return null;
424
75
  }
425
76
  const openIndex = findCallOpeningParen(request.source, request.calleeStartIndex, request.calleeEndIndex);
@@ -427,7 +78,11 @@ function extractCallsiteArgumentsFromProvider(request) {
427
78
  if (!balanced) {
428
79
  return null;
429
80
  }
430
- return callsiteFromArgumentText(request.languageId, balanced.inner);
81
+ const argCount = getCallArgumentCountFromArgumentText({
82
+ languageId: request.languageId,
83
+ argumentText: balanced.inner,
84
+ });
85
+ return argCount === null ? null : { argCount, confidence: "high" };
431
86
  }
432
87
  registerCallCompatibilityExtractors({
433
88
  extractSignature: extractCallableSignatureFromProvider,
@@ -447,84 +102,26 @@ export function extractCallsiteArguments(request) {
447
102
  }
448
103
  return provider.extractCallsite(request);
449
104
  }
450
- const callExpressionTypes = new Set([
451
- "call_expression",
452
- "call",
453
- "method_invocation",
454
- "invocation_expression",
455
- "function_call_expression",
456
- "object_creation_expression",
457
- ]);
458
- const argumentListTypes = new Set(["argument_list", "arguments", "value_arguments", "call_suffix"]);
459
- function countTrailingClosureArguments(text) {
460
- let startIndex = 0;
461
- let count = 0;
462
- while (startIndex < text.length) {
463
- while (/\s/.test(text[startIndex] ?? "")) {
464
- startIndex += 1;
465
- }
466
- if (startIndex === text.length) {
467
- return count;
468
- }
469
- if (text[startIndex] !== "{") {
470
- return null;
471
- }
472
- let braceDepth = 0;
473
- let quote = null;
474
- let escaped = false;
475
- let closed = false;
476
- for (let index = startIndex; index < text.length; index += 1) {
477
- const char = text[index];
478
- if (quote) {
479
- if (escaped) {
480
- escaped = false;
481
- continue;
482
- }
483
- if (char === "\\") {
484
- escaped = true;
485
- continue;
486
- }
487
- if (char === quote) {
488
- quote = null;
489
- }
490
- continue;
491
- }
492
- const commentEnd = findCommentEnd(text, index);
493
- if (commentEnd !== null) {
494
- if (commentEnd < 0) {
495
- return null;
496
- }
497
- index = commentEnd - 1;
498
- continue;
499
- }
500
- if (char === '"' || char === "'" || char === "`") {
501
- quote = char;
502
- continue;
503
- }
504
- if (char === "{") {
505
- braceDepth += 1;
506
- continue;
507
- }
508
- if (char === "}") {
509
- braceDepth -= 1;
510
- if (braceDepth < 0) {
511
- return null;
512
- }
513
- if (!braceDepth) {
514
- startIndex = index + 1;
515
- count += 1;
516
- closed = true;
517
- break;
518
- }
519
- }
520
- }
521
- if (!closed) {
522
- return null;
523
- }
524
- }
525
- return count;
526
- }
527
- function findCallsiteArgumentText(request) {
105
+ /**
106
+ * Call node types recognized at a callee range. PHP member and scoped call forms stay excluded:
107
+ * callsite extraction for them remains the documented limitation it was before the shared arity
108
+ * facts existed, so no caller sees a newly counted or newly dropped callsite here.
109
+ */
110
+ const CALL_EXPRESSION_NODE_TYPES = {
111
+ call: true,
112
+ call_expression: true,
113
+ function_call_expression: true,
114
+ invocation_expression: true,
115
+ method_invocation: true,
116
+ object_creation_expression: true,
117
+ };
118
+ const callExpressionTypes = new Set(Object.keys(CALL_EXPRESSION_NODE_TYPES));
119
+ /**
120
+ * Locate and validate the call node for a callee range. The callee must sit inside the call's
121
+ * target expression, so a non-callee reference inside a call (an argument, for example) is not a
122
+ * callsite, and a trailing-closure wrapper call counts as the callsite.
123
+ */
124
+ function locateCallsiteCallNode(request) {
528
125
  if (!request.tree) {
529
126
  return null;
530
127
  }
@@ -550,64 +147,7 @@ function findCallsiteArgumentText(request) {
550
147
  if (!targetNode || request.calleeStartIndex < targetNode.startIndex || endIndex > targetNode.endIndex) {
551
148
  return null;
552
149
  }
553
- const argumentNode = callNode.childForFieldName("arguments") ??
554
- callNode.namedChildren.find((child) => argumentListTypes.has(child.type)) ??
555
- findFirstDescendantOfTypes(callNode, argumentListTypes);
556
- if (argumentNode) {
557
- let text = request.source.slice(argumentNode.startIndex, argumentNode.endIndex).trim();
558
- let trailingArgumentCount = 0;
559
- const callSuffix = argumentNode.type === "call_suffix"
560
- ? argumentNode
561
- : findFirstDescendantOfTypes(callNode, new Set(["call_suffix"]));
562
- const valueArguments = argumentNode.type === "value_arguments"
563
- ? argumentNode
564
- : findFirstDescendantOfTypes(callSuffix ?? argumentNode, new Set(["value_arguments"]));
565
- if (valueArguments) {
566
- const trailingEndIndex = callSuffix?.endIndex ?? callNode.endIndex;
567
- const trailingText = request.source.slice(valueArguments.endIndex, trailingEndIndex).trim();
568
- const count = countTrailingClosureArguments(trailingText);
569
- if (count === null) {
570
- return null;
571
- }
572
- text = request.source.slice(valueArguments.startIndex, valueArguments.endIndex).trim();
573
- trailingArgumentCount = count;
574
- }
575
- if (text.startsWith("(") && text.endsWith(")")) {
576
- return { text: text.slice(1, -1), trailingArgumentCount };
577
- }
578
- return { text, trailingArgumentCount };
579
- }
580
- if (request.languageId === "zig") {
581
- const openIndex = findOpeningParen(request.source, callNode.startIndex);
582
- const balanced = findBalancedParentheses(request.source, openIndex);
583
- return balanced ? { text: balanced.inner, trailingArgumentCount: 0 } : null;
584
- }
585
- return null;
586
- }
587
- function hasUncountableSpreadArgument(languageId, arg) {
588
- const trimmed = arg.trim();
589
- if (trimmed.startsWith("...")) {
590
- return true;
591
- }
592
- if (languageId === "python" || languageId === "ruby") {
593
- return trimmed.startsWith("*") || trimmed.startsWith("**");
594
- }
595
- if (languageId === "php") {
596
- return trimmed.startsWith("...");
597
- }
598
- return false;
599
- }
600
- function callsiteFromArgumentText(languageId, argumentText, trailingArgumentCount = 0) {
601
- const args = splitTopLevelCommaGroups(argumentText, "type-context");
602
- if (!args) {
603
- return null;
604
- }
605
- for (const arg of args) {
606
- if (hasUncountableSpreadArgument(languageId, arg)) {
607
- return null;
608
- }
609
- }
610
- return { argCount: args.length + trailingArgumentCount, confidence: "high" };
150
+ return callNode;
611
151
  }
612
152
  function isCallableChangedSymbol(symbol) {
613
153
  return (symbol.kind === SymbolKind.Function ||
@@ -636,7 +176,18 @@ function sameOverloadContainer(left, right) {
636
176
  }
637
177
  return left.parent.id === right.parent.id;
638
178
  }
639
- function hasSameFileOverloadCandidates(index, changedSymbol, languageId, source, tree) {
179
+ function changedCppCallableBinding(index, changedSymbol, parsed) {
180
+ if (parsed.sup.id !== "cpp")
181
+ return undefined;
182
+ const module = index.byFile.get(fileIdentityKey(changedSymbol.file));
183
+ if (!module)
184
+ return undefined;
185
+ const scope = getOrBuildScopeIndex(index, module.file, parsed.source, parsed.sup, module, parsed.tree);
186
+ return scope.bindings
187
+ .get(parsed.sup.normalizeIdentifier(changedSymbol.name))
188
+ ?.find((binding) => binding.kind === "function" && binding.def && sameRangeStart(binding.def, changedSymbol.range));
189
+ }
190
+ function hasSameFileOverloadCandidates(index, changedSymbol, parsed) {
640
191
  const module = index.byFile.get(fileIdentityKey(changedSymbol.file));
641
192
  if (!module) {
642
193
  return false;
@@ -645,6 +196,7 @@ function hasSameFileOverloadCandidates(index, changedSymbol, languageId, source,
645
196
  if (changedStartIndex === undefined) {
646
197
  return false;
647
198
  }
199
+ const { source, tree, sup } = parsed;
648
200
  const changedDeclaration = callableDeclarationAt(tree, changedStartIndex);
649
201
  for (const local of module.locals) {
650
202
  if (local.localName !== changedSymbol.name || sameRangeStart(local.range, changedSymbol.range)) {
@@ -659,7 +211,7 @@ function hasSameFileOverloadCandidates(index, changedSymbol, languageId, source,
659
211
  continue;
660
212
  }
661
213
  const signature = extractCallableSignature({
662
- languageId,
214
+ languageId: sup.id,
663
215
  source,
664
216
  symbolStartIndex,
665
217
  tree,
@@ -770,11 +322,62 @@ function bestGotoNode(target, symbolName, source) {
770
322
  walk(target);
771
323
  return best;
772
324
  }
773
- async function collectVerifiedCallsiteReferences(index, changedSymbol, maxRefs, shouldIncludeReference, diagnostics) {
325
+ function cppUnqualifiedCallTarget(index, file, parsed, target) {
326
+ if (parsed.sup.id !== "cpp" || target.type !== "identifier")
327
+ return null;
328
+ const module = index.byFile.get(fileIdentityKey(file));
329
+ if (!module)
330
+ return null;
331
+ const name = sliceText(target, parsed.source);
332
+ const scope = getOrBuildScopeIndex(index, file, parsed.source, parsed.sup, module, parsed.tree);
333
+ const binding = findClosestScopeBinding(scope, name, target, parsed.sup);
334
+ if (binding?.kind === "function") {
335
+ const equivalents = cppEquivalentCallableBindings(binding);
336
+ if (equivalents.length !== (binding.sameScopeFunctionBindings?.length ?? 1))
337
+ return null;
338
+ const canonical = equivalents.find((candidate) => cppCallableIsDefinition(candidate.node)) ?? equivalents[0];
339
+ const range = canonical?.def;
340
+ if (!range)
341
+ return null;
342
+ return module.locals.find((local) => sameRangeStart(local.range, range)) ?? null;
343
+ }
344
+ // A local variable or parameter shadows the function; member expressions and
345
+ // ambiguous overload sets cannot be recovered as unqualified calls.
346
+ if (binding && !binding.import)
347
+ return null;
348
+ const resolved = resolveNamedDefinition(index, module, file, parsed.sup, name);
349
+ if (resolved?.status !== "ok" || resolved.definition.kind !== SymbolKind.Function)
350
+ return null;
351
+ return resolved.definition;
352
+ }
353
+ async function collectVerifiedCallsiteReferences(index, changedSymbol, maxRefs, shouldIncludeReference, diagnostics, parsedDefinition, equivalentDefinitions, excludedReferences) {
774
354
  const refs = [];
775
355
  const seen = new Set();
356
+ const languageId = parsedDefinition.sup.id;
357
+ const def = {
358
+ file: changedSymbol.file,
359
+ localName: changedSymbol.name,
360
+ kind: changedSymbol.kind,
361
+ range: changedSymbol.range,
362
+ };
363
+ let candidateFiles;
364
+ if ((languageId === "c" || languageId === "cpp") && changedSymbol.kind === SymbolKind.Function) {
365
+ candidateFiles = new Set();
366
+ for (const definition of equivalentDefinitions ?? [def]) {
367
+ const module = index.byFile.get(fileIdentityKey(definition.file));
368
+ const exportedNames = module?.exports.flatMap((entry) => entry.type === "local" && sameDefinition(entry.target, definition) ? [entry.exportedAs] : []) ?? [];
369
+ if (!exportedNames.length)
370
+ exportedNames.push(definition.localName);
371
+ candidateFiles.add(fileIdentityKey(definition.file));
372
+ for (const file of getCachedReferenceCandidateFiles(index, definition, exportedNames, false, languageId)) {
373
+ candidateFiles.add(fileIdentityKey(file));
374
+ }
375
+ }
376
+ }
776
377
  for (const module of index.byFile.values()) {
777
378
  const file = module.file;
379
+ if (candidateFiles && !candidateFiles.has(fileIdentityKey(file)))
380
+ continue;
778
381
  if (refs.length >= maxRefs) {
779
382
  break;
780
383
  }
@@ -802,18 +405,16 @@ async function collectVerifiedCallsiteReferences(index, changedSymbol, maxRefs,
802
405
  file,
803
406
  line: gotoNode.startPosition.row + 1,
804
407
  column: gotoNode.startPosition.column + 1,
805
- });
806
- if (result.status === "ok") {
807
- const def = {
808
- file: changedSymbol.file,
809
- localName: changedSymbol.name,
810
- kind: changedSymbol.kind,
811
- range: changedSymbol.range,
812
- };
813
- if (sameDefinition(result.definition, def)) {
408
+ }, parsed);
409
+ // Navigation rejects invalid C++ arity. Compatibility diagnostics need
410
+ // the unique lexical/import binding before judging the argument count.
411
+ const definition = result.status === "ok" ? result.definition : cppUnqualifiedCallTarget(index, file, parsed, target);
412
+ if (definition) {
413
+ if (sameDefinition(definition, def) ||
414
+ equivalentDefinitions?.some((candidate) => sameDefinition(definition, candidate))) {
814
415
  const range = toRange(gotoNode);
815
416
  const key = `${fileIdentityKey(file)}:${range.start.line}:${range.start.column}`;
816
- if (!seen.has(key)) {
417
+ if (!seen.has(key) && !excludedReferences.has(key)) {
817
418
  seen.add(key);
818
419
  refs.push({ file, range });
819
420
  }
@@ -851,8 +452,82 @@ function incrementSkippedReason(diagnostics, reason) {
851
452
  }
852
453
  diagnostics.skippedByReason[reason] = (diagnostics.skippedByReason[reason] ?? 0) + 1;
853
454
  }
455
+ /** Declaration containers whose `name` field names the receiver type at a member call. */
456
+ const OWNER_CONTAINER_TYPES = {
457
+ class_declaration: true,
458
+ class_definition: true,
459
+ class_specifier: true,
460
+ impl_item: true,
461
+ interface_declaration: true,
462
+ object_declaration: true,
463
+ struct_specifier: true,
464
+ trait_item: true,
465
+ };
466
+ function ownerTypeNameOf(declaration, source) {
467
+ let current = declaration.parent;
468
+ while (current) {
469
+ if (OWNER_CONTAINER_TYPES[current.type]) {
470
+ const name = current.childForFieldName("name");
471
+ return name ? sliceText(name, source) : null;
472
+ }
473
+ current = current.parent;
474
+ }
475
+ return null;
476
+ }
477
+ /**
478
+ * Resolve which receiver binding form a callsite uses. Python bare calls reach the plain function
479
+ * and pass the receiver explicitly; Python member calls on a provably class-valued receiver do the
480
+ * same only for instance methods, because class and static methods bind (or declare) no instance
481
+ * receiver. Rust `Type::target(...)` calls are unbound UFCS forms. C# follows the shared member
482
+ * lookup rule: resolved extension callsites are static-class (`Ext.M(value)`, `Alias.Ext.M(value)`)
483
+ * or bare calls inside the class, all of which pass the `this` receiver explicitly.
484
+ * Everything else supplies the receiver through the call form.
485
+ */
486
+ function callBindingForm(input) {
487
+ const { languageId, callNode, source, parsedCallsite, file, index, declarationKind, ownerTypeName } = input;
488
+ const callee = callTargetNode(callNode);
489
+ if (languageId === "rust") {
490
+ return callee?.type === "scoped_identifier" ? "unbound" : "bound";
491
+ }
492
+ if (languageId === "csharp") {
493
+ return memberLookupBinding(languageId);
494
+ }
495
+ if (languageId !== "python" || !callee) {
496
+ return "bound";
497
+ }
498
+ if (callee.type === "identifier") {
499
+ return "unbound";
500
+ }
501
+ if (callee.type !== "attribute") {
502
+ return "bound";
503
+ }
504
+ const receiver = callee.namedChildren[0] ?? null;
505
+ if (!receiver) {
506
+ return "bound";
507
+ }
508
+ const receiverText = sliceText(receiver, source).trim();
509
+ if (receiverText === "self" || receiverText === "cls" || receiverText === "super()") {
510
+ return "bound";
511
+ }
512
+ if (declarationKind !== "instance-method") {
513
+ return "bound";
514
+ }
515
+ if (ownerTypeName && receiverText === ownerTypeName) {
516
+ return "unbound";
517
+ }
518
+ if (receiver.type === "identifier") {
519
+ const module = index.byFile.get(fileIdentityKey(file));
520
+ if (module) {
521
+ const resolved = resolveNamedDefinition(index, module, file, parsedCallsite.sup, receiverText);
522
+ if (resolved?.status === "ok" && resolved.definition.kind === SymbolKind.Class) {
523
+ return "unbound";
524
+ }
525
+ }
526
+ }
527
+ return "bound";
528
+ }
854
529
  async function buildCallCompatibilityHintForReference(input) {
855
- const { index, changedSymbol, signature, ref, callerRangeIndex, diagnostics, projectRoot } = input;
530
+ const { index, changedSymbol, signature, unboundSignature, declarationKind, ownerTypeName, ref, callerRangeIndex, diagnostics, projectRoot, } = input;
856
531
  if (fileIdentityKey(ref.file) === fileIdentityKey(changedSymbol.file) &&
857
532
  sameRangeStart(ref.range, changedSymbol.range)) {
858
533
  return null;
@@ -879,7 +554,30 @@ async function buildCallCompatibilityHintForReference(input) {
879
554
  }
880
555
  return null;
881
556
  }
882
- const compatibility = classifyCompatibility(signature, actual);
557
+ // Pick the arity for the call form: an unbound call passes the receiver as its first argument,
558
+ // so it must be compared against the receiver-inclusive range instead of the bound one.
559
+ let expected = signature;
560
+ const hasDistinctUnboundForm = unboundSignature !== null &&
561
+ (unboundSignature.minArgs !== signature.minArgs || unboundSignature.maxArgs !== signature.maxArgs);
562
+ if (hasDistinctUnboundForm) {
563
+ const callNode = parsedCallsite.tree ? locateCallsiteCallNode(callsiteRequest) : null;
564
+ const binding = callNode
565
+ ? callBindingForm({
566
+ languageId: parsedCallsite.sup.id,
567
+ callNode,
568
+ source: parsedCallsite.source,
569
+ parsedCallsite,
570
+ file: ref.file,
571
+ index,
572
+ declarationKind,
573
+ ownerTypeName,
574
+ })
575
+ : "bound";
576
+ if (binding === "unbound" && unboundSignature) {
577
+ expected = unboundSignature;
578
+ }
579
+ }
580
+ const compatibility = classifyCompatibility(expected, actual);
883
581
  const callerSymbolId = findCallerSymbolId(callerRangeIndex, ref);
884
582
  const callsiteFile = projectRoot ? path.relative(projectRoot, ref.file).replace(/\\/g, "/") : ref.file;
885
583
  return {
@@ -888,7 +586,7 @@ async function buildCallCompatibilityHintForReference(input) {
888
586
  callsiteFile,
889
587
  callsiteRange: ref.range,
890
588
  ...(callerSymbolId ? { callerSymbolId } : {}),
891
- expected: signature,
589
+ expected,
892
590
  actual,
893
591
  };
894
592
  }
@@ -939,17 +637,76 @@ export async function attachCallCompatibilityHints(index, changedSymbols, option
939
637
  incrementSkippedReason(diagnostics, "signature_unknown");
940
638
  continue;
941
639
  }
942
- if (hasSameFileOverloadCandidates(index, changedSymbol, parsedDefinition.sup.id, parsedDefinition.source, parsedDefinition.tree)) {
640
+ // Receiver-bearing declarations accept different argument counts per call form: a bound call
641
+ // never passes the receiver, an unbound call does. Both arities are merged below so prototype
642
+ // defaults apply to each.
643
+ const unboundSignature = extractCallableSignature({
644
+ languageId: parsedDefinition.sup.id,
645
+ source: parsedDefinition.source,
646
+ symbolStartIndex: changedSymbol.range.start.index ?? 0,
647
+ tree: parsedDefinition.tree,
648
+ binding: "unbound",
649
+ });
650
+ const hasDistinctUnboundForm = unboundSignature !== null &&
651
+ (unboundSignature.minArgs !== signature.minArgs || unboundSignature.maxArgs !== signature.maxArgs);
652
+ const arityTargets = hasDistinctUnboundForm && unboundSignature ? [signature, unboundSignature] : [signature];
653
+ const cppBinding = changedCppCallableBinding(index, changedSymbol, parsedDefinition);
654
+ const equivalentBindings = cppBinding ? cppEquivalentCallableBindings(cppBinding) : undefined;
655
+ const hasOverloads = cppBinding && equivalentBindings
656
+ ? equivalentBindings.length !== (cppBinding.sameScopeFunctionBindings?.length ?? 1)
657
+ : hasSameFileOverloadCandidates(index, changedSymbol, parsedDefinition);
658
+ if (hasOverloads) {
943
659
  incrementSkippedReason(diagnostics, "overload_set");
944
660
  continue;
945
661
  }
946
- const referenceScanLimit = referenceScanLimitForCallsites(options.maxRefs);
947
- const referenceDef = {
662
+ const module = index.byFile.get(fileIdentityKey(changedSymbol.file));
663
+ const referenceDef = module?.locals.find((local) => local.kind === changedSymbol.kind && sameRangeStart(local.range, changedSymbol.range)) ?? {
948
664
  file: changedSymbol.file,
949
665
  localName: changedSymbol.name,
950
666
  kind: changedSymbol.kind,
951
667
  range: changedSymbol.range,
952
668
  };
669
+ const equivalentDefinitions = parsedDefinition.sup.id === "cpp"
670
+ ? await getCppEquivalentCallableDefinitions(index, referenceDef, parsedDefinition)
671
+ : undefined;
672
+ // Default arguments can live on a prototype rather than its definition.
673
+ // Both sites describe the same accepted range.
674
+ if (equivalentDefinitions) {
675
+ for (const definition of equivalentDefinitions) {
676
+ const startIndex = definition.range.start.index;
677
+ if (startIndex === undefined)
678
+ continue;
679
+ const parsed = fileIdentityKey(definition.file) === fileIdentityKey(referenceDef.file)
680
+ ? parsedDefinition
681
+ : await tryEnsureParsedContext(definition.file, index.parsed?.get(fileIdentityKey(definition.file)), index.languageExtensions, diagnostics);
682
+ if (!parsed)
683
+ continue;
684
+ const node = parsed.tree.rootNode.descendantForIndex(startIndex, startIndex);
685
+ const shape = cppCallableShapeForNode(node);
686
+ if (!shape)
687
+ continue;
688
+ for (const target of arityTargets) {
689
+ target.minArgs = Math.min(target.minArgs, shape.minArity);
690
+ if (target.maxArgs === null || shape.maxArity === null) {
691
+ target.maxArgs = null;
692
+ }
693
+ else {
694
+ target.maxArgs = Math.max(target.maxArgs, shape.maxArity);
695
+ }
696
+ }
697
+ }
698
+ }
699
+ const changedStartIndex = changedSymbol.range.start.index;
700
+ const declarationNode = changedStartIndex === undefined ? null : callableDeclarationAt(parsedDefinition.tree, changedStartIndex);
701
+ const declarationKind = declarationNode
702
+ ? getCallableDeclarationKind({
703
+ languageId: parsedDefinition.sup.id,
704
+ source: parsedDefinition.source,
705
+ declaration: declarationNode,
706
+ })
707
+ : null;
708
+ const ownerTypeName = declarationNode ? ownerTypeNameOf(declarationNode, parsedDefinition.source) : null;
709
+ const referenceScanLimit = referenceScanLimitForCallsites(options.maxRefs);
953
710
  if (options.workBudget) {
954
711
  recordReferenceLookupStarted(options.workBudget);
955
712
  }
@@ -961,7 +718,7 @@ export async function attachCallCompatibilityHints(index, changedSymbols, option
961
718
  if (referenceResult.status === "ok") {
962
719
  refs = referenceResult.references.filter((ref) => shouldIncludeReference(ref.file));
963
720
  }
964
- const seenRefs = new Set(refs.map((ref) => `${ref.file}:${ref.range.start.line}:${ref.range.start.column}`));
721
+ const seenRefs = new Set(refs.map((ref) => `${fileIdentityKey(ref.file)}:${ref.range.start.line}:${ref.range.start.column}`));
965
722
  const hints = [];
966
723
  let consideredCallsites = 0;
967
724
  const addHintForReference = async (ref) => {
@@ -972,6 +729,9 @@ export async function attachCallCompatibilityHints(index, changedSymbols, option
972
729
  index,
973
730
  changedSymbol,
974
731
  signature,
732
+ unboundSignature: hasDistinctUnboundForm ? unboundSignature : null,
733
+ declarationKind,
734
+ ownerTypeName,
975
735
  ref,
976
736
  callerRangeIndex,
977
737
  diagnostics,
@@ -989,16 +749,20 @@ export async function attachCallCompatibilityHints(index, changedSymbols, option
989
749
  }
990
750
  await addHintForReference(ref);
991
751
  }
992
- const shouldRunVerifiedScan = consideredCallsites < options.maxRefs && (referenceResult.status !== "ok" || !consideredCallsites);
752
+ const shouldRunVerifiedScan = consideredCallsites < options.maxRefs &&
753
+ (parsedDefinition.sup.id === "c" ||
754
+ parsedDefinition.sup.id === "cpp" ||
755
+ referenceResult.status !== "ok" ||
756
+ !consideredCallsites);
993
757
  if (shouldRunVerifiedScan) {
994
758
  const verifiedScanLimit = Math.max(0, Math.min(referenceScanLimit - refs.length, options.maxRefs - consideredCallsites));
995
759
  if (verifiedScanLimit) {
996
- const verifiedCallsites = await collectVerifiedCallsiteReferences(index, changedSymbol, verifiedScanLimit, shouldIncludeReference, diagnostics);
760
+ const verifiedCallsites = await collectVerifiedCallsiteReferences(index, changedSymbol, verifiedScanLimit, shouldIncludeReference, diagnostics, parsedDefinition, equivalentDefinitions, seenRefs);
997
761
  for (const ref of verifiedCallsites) {
998
762
  if (consideredCallsites >= options.maxRefs) {
999
763
  break;
1000
764
  }
1001
- const key = `${ref.file}:${ref.range.start.line}:${ref.range.start.column}`;
765
+ const key = `${fileIdentityKey(ref.file)}:${ref.range.start.line}:${ref.range.start.column}`;
1002
766
  if (seenRefs.has(key)) {
1003
767
  continue;
1004
768
  }