@lzehrung/codegraph 2.3.31 → 3.0.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 (596) hide show
  1. package/README.md +33 -141
  2. package/codegraph-skill/codegraph/SKILL.md +8 -6
  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/call-hierarchy.js +2 -4
  7. package/dist/agent/call-hierarchy.js.map +1 -1
  8. package/dist/agent/explore.d.ts +1 -1
  9. package/dist/agent/explore.d.ts.map +1 -1
  10. package/dist/agent/explore.js +3 -2
  11. package/dist/agent/explore.js.map +1 -1
  12. package/dist/agent/refactor-plan.js +2 -4
  13. package/dist/agent/refactor-plan.js.map +1 -1
  14. package/dist/agent/rename-preview.d.ts.map +1 -1
  15. package/dist/agent/rename-preview.js +4 -3
  16. package/dist/agent/rename-preview.js.map +1 -1
  17. package/dist/agent/search.d.ts.map +1 -1
  18. package/dist/agent/search.js +5 -3
  19. package/dist/agent/search.js.map +1 -1
  20. package/dist/agent/semantic-symbols.d.ts.map +1 -1
  21. package/dist/agent/semantic-symbols.js +2 -3
  22. package/dist/agent/semantic-symbols.js.map +1 -1
  23. package/dist/agent/session.d.ts +3 -0
  24. package/dist/agent/session.d.ts.map +1 -1
  25. package/dist/agent/session.js +10 -2
  26. package/dist/agent/session.js.map +1 -1
  27. package/dist/agent/type-hierarchy.js +2 -4
  28. package/dist/agent/type-hierarchy.js.map +1 -1
  29. package/dist/agent/workspace-symbols.d.ts.map +1 -1
  30. package/dist/agent/workspace-symbols.js +2 -3
  31. package/dist/agent/workspace-symbols.js.map +1 -1
  32. package/dist/agent-tools.d.ts +0 -4
  33. package/dist/agent-tools.d.ts.map +1 -1
  34. package/dist/agent-tools.js +3 -6
  35. package/dist/agent-tools.js.map +1 -1
  36. package/dist/analysis-summary.d.ts +8 -4
  37. package/dist/analysis-summary.d.ts.map +1 -1
  38. package/dist/analysis-summary.js +15 -66
  39. package/dist/analysis-summary.js.map +1 -1
  40. package/dist/bin/cli.js +51145 -41770
  41. package/dist/bin/query-index-worker.js +122 -82
  42. package/dist/cli/affected.d.ts.map +1 -1
  43. package/dist/cli/affected.js +4 -1
  44. package/dist/cli/affected.js.map +1 -1
  45. package/dist/cli/command-catalog.js +1 -1
  46. package/dist/cli/command-catalog.js.map +1 -1
  47. package/dist/cli/command-table.d.ts.map +1 -1
  48. package/dist/cli/command-table.js +9 -17
  49. package/dist/cli/command-table.js.map +1 -1
  50. package/dist/cli/context.js +10 -10
  51. package/dist/cli/context.js.map +1 -1
  52. package/dist/cli/drift.d.ts +0 -2
  53. package/dist/cli/drift.d.ts.map +1 -1
  54. package/dist/cli/drift.js +0 -1
  55. package/dist/cli/drift.js.map +1 -1
  56. package/dist/cli/graph-delta.d.ts +0 -2
  57. package/dist/cli/graph-delta.d.ts.map +1 -1
  58. package/dist/cli/graph-delta.js +0 -4
  59. package/dist/cli/graph-delta.js.map +1 -1
  60. package/dist/cli/graph-queries.d.ts.map +1 -1
  61. package/dist/cli/graph-queries.js +27 -1
  62. package/dist/cli/graph-queries.js.map +1 -1
  63. package/dist/cli/graph.d.ts +0 -3
  64. package/dist/cli/graph.d.ts.map +1 -1
  65. package/dist/cli/graph.js +4 -14
  66. package/dist/cli/graph.js.map +1 -1
  67. package/dist/cli/help.d.ts +34 -34
  68. package/dist/cli/help.d.ts.map +1 -1
  69. package/dist/cli/help.js +9 -14
  70. package/dist/cli/help.js.map +1 -1
  71. package/dist/cli/impact.d.ts +0 -2
  72. package/dist/cli/impact.d.ts.map +1 -1
  73. package/dist/cli/impact.js +0 -1
  74. package/dist/cli/impact.js.map +1 -1
  75. package/dist/cli/index.d.ts +0 -2
  76. package/dist/cli/index.d.ts.map +1 -1
  77. package/dist/cli/index.js +5 -6
  78. package/dist/cli/index.js.map +1 -1
  79. package/dist/cli/inspect.d.ts +0 -2
  80. package/dist/cli/inspect.d.ts.map +1 -1
  81. package/dist/cli/inspect.js +5 -8
  82. package/dist/cli/inspect.js.map +1 -1
  83. package/dist/cli/invocation-context.d.ts +0 -3
  84. package/dist/cli/invocation-context.d.ts.map +1 -1
  85. package/dist/cli/invocation-context.js +4 -16
  86. package/dist/cli/invocation-context.js.map +1 -1
  87. package/dist/cli/navigation.d.ts +0 -2
  88. package/dist/cli/navigation.d.ts.map +1 -1
  89. package/dist/cli/navigation.js +0 -1
  90. package/dist/cli/navigation.js.map +1 -1
  91. package/dist/cli/options.d.ts.map +1 -1
  92. package/dist/cli/options.js +4 -14
  93. package/dist/cli/options.js.map +1 -1
  94. package/dist/cli/review.d.ts +0 -2
  95. package/dist/cli/review.d.ts.map +1 -1
  96. package/dist/cli/review.js +0 -5
  97. package/dist/cli/review.js.map +1 -1
  98. package/dist/cli/root-policy.d.ts +0 -2
  99. package/dist/cli/root-policy.d.ts.map +1 -1
  100. package/dist/cli/root-policy.js +0 -8
  101. package/dist/cli/root-policy.js.map +1 -1
  102. package/dist/cli/server.d.ts.map +1 -1
  103. package/dist/cli/server.js +0 -2
  104. package/dist/cli/server.js.map +1 -1
  105. package/dist/drift/artifact.d.ts.map +1 -1
  106. package/dist/drift/artifact.js +15 -18
  107. package/dist/drift/artifact.js.map +1 -1
  108. package/dist/drift/compare.js +1 -1
  109. package/dist/drift/compare.js.map +1 -1
  110. package/dist/drift/git.d.ts.map +1 -1
  111. package/dist/drift/git.js +0 -1
  112. package/dist/drift/git.js.map +1 -1
  113. package/dist/drift/snapshot.d.ts.map +1 -1
  114. package/dist/drift/snapshot.js +5 -7
  115. package/dist/drift/snapshot.js.map +1 -1
  116. package/dist/drift/types.d.ts +2 -2
  117. package/dist/drift/types.d.ts.map +1 -1
  118. package/dist/drift/types.js.map +1 -1
  119. package/dist/duplicates/unit-cache.d.ts +0 -1
  120. package/dist/duplicates/unit-cache.d.ts.map +1 -1
  121. package/dist/duplicates/unit-cache.js +3 -11
  122. package/dist/duplicates/unit-cache.js.map +1 -1
  123. package/dist/duplicates/units.d.ts +5 -5
  124. package/dist/duplicates/units.d.ts.map +1 -1
  125. package/dist/duplicates/units.js +25 -88
  126. package/dist/duplicates/units.js.map +1 -1
  127. package/dist/graph-builder.d.ts +0 -6
  128. package/dist/graph-builder.d.ts.map +1 -1
  129. package/dist/graph-builder.js +6 -11
  130. package/dist/graph-builder.js.map +1 -1
  131. package/dist/graph-edge-collector.d.ts +4 -6
  132. package/dist/graph-edge-collector.d.ts.map +1 -1
  133. package/dist/graph-edge-collector.js +31 -26
  134. package/dist/graph-edge-collector.js.map +1 -1
  135. package/dist/graphs/angularjs.d.ts.map +1 -1
  136. package/dist/graphs/angularjs.js +2 -1
  137. package/dist/graphs/angularjs.js.map +1 -1
  138. package/dist/graphs/edge-resolution.d.ts +4 -1
  139. package/dist/graphs/edge-resolution.d.ts.map +1 -1
  140. package/dist/graphs/edge-resolution.js +24 -76
  141. package/dist/graphs/edge-resolution.js.map +1 -1
  142. package/dist/graphs/specifiers.d.ts +4 -13
  143. package/dist/graphs/specifiers.d.ts.map +1 -1
  144. package/dist/graphs/specifiers.js +80 -173
  145. package/dist/graphs/specifiers.js.map +1 -1
  146. package/dist/graphs/symbol-graph-detailed/ast.d.ts +20 -0
  147. package/dist/graphs/symbol-graph-detailed/ast.d.ts.map +1 -1
  148. package/dist/graphs/symbol-graph-detailed/ast.js +154 -15
  149. package/dist/graphs/symbol-graph-detailed/ast.js.map +1 -1
  150. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts +60 -8
  151. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
  152. package/dist/graphs/symbol-graph-detailed/edge-passes.js +997 -168
  153. package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
  154. package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts +2 -1
  155. package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts.map +1 -1
  156. package/dist/graphs/symbol-graph-detailed/import-aliases.js +150 -7
  157. package/dist/graphs/symbol-graph-detailed/import-aliases.js.map +1 -1
  158. package/dist/graphs/symbol-graph-detailed/member-chains.d.ts +1 -0
  159. package/dist/graphs/symbol-graph-detailed/member-chains.d.ts.map +1 -1
  160. package/dist/graphs/symbol-graph-detailed/member-chains.js +3 -1
  161. package/dist/graphs/symbol-graph-detailed/member-chains.js.map +1 -1
  162. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +141 -25
  163. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
  164. package/dist/graphs/symbol-graph-detailed/receiver-calls.js +1015 -166
  165. package/dist/graphs/symbol-graph-detailed/receiver-calls.js.map +1 -1
  166. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  167. package/dist/graphs/symbol-graph-detailed.js +449 -46
  168. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  169. package/dist/graphs/symbol-graph.d.ts +2 -0
  170. package/dist/graphs/symbol-graph.d.ts.map +1 -1
  171. package/dist/graphs/symbol-graph.js +34 -16
  172. package/dist/graphs/symbol-graph.js.map +1 -1
  173. package/dist/graphs/types.d.ts +0 -4
  174. package/dist/graphs/types.d.ts.map +1 -1
  175. package/dist/graphs.d.ts +1 -1
  176. package/dist/graphs.d.ts.map +1 -1
  177. package/dist/impact/call-compatibility/providers/index.d.ts +4 -4
  178. package/dist/impact/call-compatibility/providers/index.d.ts.map +1 -1
  179. package/dist/impact/call-compatibility/providers/index.js +6 -6
  180. package/dist/impact/call-compatibility/providers/index.js.map +1 -1
  181. package/dist/impact/call-compatibility/providers/types.d.ts +2 -0
  182. package/dist/impact/call-compatibility/providers/types.d.ts.map +1 -1
  183. package/dist/impact/call-compatibility/types.d.ts +6 -0
  184. package/dist/impact/call-compatibility/types.d.ts.map +1 -1
  185. package/dist/impact/call-compatibility.d.ts.map +1 -1
  186. package/dist/impact/call-compatibility.js +316 -526
  187. package/dist/impact/call-compatibility.js.map +1 -1
  188. package/dist/impact/map.js +1 -0
  189. package/dist/impact/map.js.map +1 -1
  190. package/dist/impact/reference-cache.d.ts.map +1 -1
  191. package/dist/impact/reference-cache.js +2 -2
  192. package/dist/impact/reference-cache.js.map +1 -1
  193. package/dist/index.d.ts +2 -2
  194. package/dist/index.d.ts.map +1 -1
  195. package/dist/index.js +1 -1
  196. package/dist/index.js.map +1 -1
  197. package/dist/indexer/ambiguous-resolution.d.ts +11 -0
  198. package/dist/indexer/ambiguous-resolution.d.ts.map +1 -0
  199. package/dist/indexer/ambiguous-resolution.js +19 -0
  200. package/dist/indexer/ambiguous-resolution.js.map +1 -0
  201. package/dist/indexer/build-cache/module-cache.d.ts +39 -1
  202. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  203. package/dist/indexer/build-cache/module-cache.js +218 -21
  204. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  205. package/dist/indexer/build-cache/options.d.ts +30 -44
  206. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  207. package/dist/indexer/build-cache/options.js +32 -71
  208. package/dist/indexer/build-cache/options.js.map +1 -1
  209. package/dist/indexer/build-cache/project-snapshot.d.ts +3 -3
  210. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  211. package/dist/indexer/build-cache/project-snapshot.js +164 -84
  212. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  213. package/dist/indexer/build-cache/reports.d.ts +0 -2
  214. package/dist/indexer/build-cache/reports.d.ts.map +1 -1
  215. package/dist/indexer/build-cache/reports.js +0 -97
  216. package/dist/indexer/build-cache/reports.js.map +1 -1
  217. package/dist/indexer/build-cache/resolver-environment.d.ts.map +1 -1
  218. package/dist/indexer/build-cache/resolver-environment.js +32 -2
  219. package/dist/indexer/build-cache/resolver-environment.js.map +1 -1
  220. package/dist/indexer/build-cache.d.ts +2 -2
  221. package/dist/indexer/build-cache.d.ts.map +1 -1
  222. package/dist/indexer/build-cache.js +2 -2
  223. package/dist/indexer/build-cache.js.map +1 -1
  224. package/dist/indexer/build-index.d.ts.map +1 -1
  225. package/dist/indexer/build-index.js +656 -71
  226. package/dist/indexer/build-index.js.map +1 -1
  227. package/dist/indexer/build-workers.d.ts.map +1 -1
  228. package/dist/indexer/build-workers.js +9 -9
  229. package/dist/indexer/build-workers.js.map +1 -1
  230. package/dist/indexer/call-hierarchy.js +1 -1
  231. package/dist/indexer/call-hierarchy.js.map +1 -1
  232. package/dist/indexer/callable-identity.d.ts +24 -0
  233. package/dist/indexer/callable-identity.d.ts.map +1 -0
  234. package/dist/indexer/callable-identity.js +111 -0
  235. package/dist/indexer/callable-identity.js.map +1 -0
  236. package/dist/indexer/compilation-units.d.ts +103 -0
  237. package/dist/indexer/compilation-units.d.ts.map +1 -0
  238. package/dist/indexer/compilation-units.js +607 -0
  239. package/dist/indexer/compilation-units.js.map +1 -0
  240. package/dist/indexer/cpp-callables.d.ts +25 -0
  241. package/dist/indexer/cpp-callables.d.ts.map +1 -0
  242. package/dist/indexer/cpp-callables.js +562 -0
  243. package/dist/indexer/cpp-callables.js.map +1 -0
  244. package/dist/indexer/declaration-visibility.d.ts +43 -2
  245. package/dist/indexer/declaration-visibility.d.ts.map +1 -1
  246. package/dist/indexer/declaration-visibility.js +158 -2
  247. package/dist/indexer/declaration-visibility.js.map +1 -1
  248. package/dist/indexer/expand-star-imports.d.ts +6 -1
  249. package/dist/indexer/expand-star-imports.d.ts.map +1 -1
  250. package/dist/indexer/expand-star-imports.js +131 -37
  251. package/dist/indexer/expand-star-imports.js.map +1 -1
  252. package/dist/indexer/finalize.d.ts.map +1 -1
  253. package/dist/indexer/finalize.js +0 -1
  254. package/dist/indexer/finalize.js.map +1 -1
  255. package/dist/indexer/import-resolution-tables.d.ts +72 -0
  256. package/dist/indexer/import-resolution-tables.d.ts.map +1 -0
  257. package/dist/indexer/import-resolution-tables.js +137 -0
  258. package/dist/indexer/import-resolution-tables.js.map +1 -0
  259. package/dist/indexer/import-types.d.ts +54 -0
  260. package/dist/indexer/import-types.d.ts.map +1 -1
  261. package/dist/indexer/import-types.js +24 -1
  262. package/dist/indexer/import-types.js.map +1 -1
  263. package/dist/indexer/imports/context.d.ts +16 -1
  264. package/dist/indexer/imports/context.d.ts.map +1 -1
  265. package/dist/indexer/imports/import-binding-tables.d.ts +13 -1
  266. package/dist/indexer/imports/import-binding-tables.d.ts.map +1 -1
  267. package/dist/indexer/imports/import-binding-tables.js +149 -30
  268. package/dist/indexer/imports/import-binding-tables.js.map +1 -1
  269. package/dist/indexer/imports/js-text-imports.js +4 -4
  270. package/dist/indexer/imports/js-text-imports.js.map +1 -1
  271. package/dist/indexer/imports/native-captures.d.ts.map +1 -1
  272. package/dist/indexer/imports/native-captures.js +24 -6
  273. package/dist/indexer/imports/native-captures.js.map +1 -1
  274. package/dist/indexer/imports/python.d.ts +10 -2
  275. package/dist/indexer/imports/python.d.ts.map +1 -1
  276. package/dist/indexer/imports/python.js +128 -112
  277. package/dist/indexer/imports/python.js.map +1 -1
  278. package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -1
  279. package/dist/indexer/imports/text-import-extractors.js +68 -19
  280. package/dist/indexer/imports/text-import-extractors.js.map +1 -1
  281. package/dist/indexer/imports.d.ts +3 -4
  282. package/dist/indexer/imports.d.ts.map +1 -1
  283. package/dist/indexer/imports.js +116 -72
  284. package/dist/indexer/imports.js.map +1 -1
  285. package/dist/indexer/incremental-plan.d.ts +33 -0
  286. package/dist/indexer/incremental-plan.d.ts.map +1 -1
  287. package/dist/indexer/incremental-plan.js +203 -1
  288. package/dist/indexer/incremental-plan.js.map +1 -1
  289. package/dist/indexer/locals-and-exports.d.ts +3 -2
  290. package/dist/indexer/locals-and-exports.d.ts.map +1 -1
  291. package/dist/indexer/locals-and-exports.js +659 -78
  292. package/dist/indexer/locals-and-exports.js.map +1 -1
  293. package/dist/indexer/member-selection.d.ts +46 -0
  294. package/dist/indexer/member-selection.d.ts.map +1 -0
  295. package/dist/indexer/member-selection.js +169 -0
  296. package/dist/indexer/member-selection.js.map +1 -0
  297. package/dist/indexer/name-lookup-policies/c-family.d.ts +7 -0
  298. package/dist/indexer/name-lookup-policies/c-family.d.ts.map +1 -0
  299. package/dist/indexer/name-lookup-policies/c-family.js +137 -0
  300. package/dist/indexer/name-lookup-policies/c-family.js.map +1 -0
  301. package/dist/indexer/name-lookup-policies/csharp-using-static.d.ts +11 -0
  302. package/dist/indexer/name-lookup-policies/csharp-using-static.d.ts.map +1 -0
  303. package/dist/indexer/name-lookup-policies/csharp-using-static.js +136 -0
  304. package/dist/indexer/name-lookup-policies/csharp-using-static.js.map +1 -0
  305. package/dist/indexer/name-lookup-policies/implicit-self.d.ts +10 -0
  306. package/dist/indexer/name-lookup-policies/implicit-self.d.ts.map +1 -0
  307. package/dist/indexer/name-lookup-policies/implicit-self.js +119 -0
  308. package/dist/indexer/name-lookup-policies/implicit-self.js.map +1 -0
  309. package/dist/indexer/name-lookup-policies/index.d.ts +3 -0
  310. package/dist/indexer/name-lookup-policies/index.d.ts.map +1 -0
  311. package/dist/indexer/name-lookup-policies/index.js +132 -0
  312. package/dist/indexer/name-lookup-policies/index.js.map +1 -0
  313. package/dist/indexer/name-lookup-policies/php.d.ts +3 -0
  314. package/dist/indexer/name-lookup-policies/php.d.ts.map +1 -0
  315. package/dist/indexer/name-lookup-policies/php.js +82 -0
  316. package/dist/indexer/name-lookup-policies/php.js.map +1 -0
  317. package/dist/indexer/name-resolution-types.d.ts +101 -0
  318. package/dist/indexer/name-resolution-types.d.ts.map +1 -0
  319. package/dist/indexer/name-resolution-types.js +2 -0
  320. package/dist/indexer/name-resolution-types.js.map +1 -0
  321. package/dist/indexer/name-resolution.d.ts +57 -0
  322. package/dist/indexer/name-resolution.d.ts.map +1 -0
  323. package/dist/indexer/name-resolution.js +204 -0
  324. package/dist/indexer/name-resolution.js.map +1 -0
  325. package/dist/indexer/navigation-cpp.d.ts +58 -0
  326. package/dist/indexer/navigation-cpp.d.ts.map +1 -0
  327. package/dist/indexer/navigation-cpp.js +935 -0
  328. package/dist/indexer/navigation-cpp.js.map +1 -0
  329. package/dist/indexer/navigation-goto.d.ts +115 -3
  330. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  331. package/dist/indexer/navigation-goto.js +2469 -190
  332. package/dist/indexer/navigation-goto.js.map +1 -1
  333. package/dist/indexer/navigation-local.d.ts +21 -2
  334. package/dist/indexer/navigation-local.d.ts.map +1 -1
  335. package/dist/indexer/navigation-local.js +520 -63
  336. package/dist/indexer/navigation-local.js.map +1 -1
  337. package/dist/indexer/navigation-php.d.ts +66 -0
  338. package/dist/indexer/navigation-php.d.ts.map +1 -1
  339. package/dist/indexer/navigation-php.js +287 -4
  340. package/dist/indexer/navigation-php.js.map +1 -1
  341. package/dist/indexer/navigation-provenance.d.ts +1 -1
  342. package/dist/indexer/navigation-provenance.d.ts.map +1 -1
  343. package/dist/indexer/navigation-provenance.js +4 -13
  344. package/dist/indexer/navigation-provenance.js.map +1 -1
  345. package/dist/indexer/navigation-references.d.ts +73 -6
  346. package/dist/indexer/navigation-references.d.ts.map +1 -1
  347. package/dist/indexer/navigation-references.js +661 -67
  348. package/dist/indexer/navigation-references.js.map +1 -1
  349. package/dist/indexer/navigation-resolve.d.ts +46 -2
  350. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  351. package/dist/indexer/navigation-resolve.js +599 -193
  352. package/dist/indexer/navigation-resolve.js.map +1 -1
  353. package/dist/indexer/navigation.d.ts +29 -2
  354. package/dist/indexer/navigation.d.ts.map +1 -1
  355. package/dist/indexer/navigation.js +1092 -153
  356. package/dist/indexer/navigation.js.map +1 -1
  357. package/dist/indexer/parse-context.d.ts +2 -3
  358. package/dist/indexer/parse-context.d.ts.map +1 -1
  359. package/dist/indexer/parse-context.js +8 -21
  360. package/dist/indexer/parse-context.js.map +1 -1
  361. package/dist/indexer/php-namespace-symbols.d.ts +66 -0
  362. package/dist/indexer/php-namespace-symbols.d.ts.map +1 -0
  363. package/dist/indexer/php-namespace-symbols.js +342 -0
  364. package/dist/indexer/php-namespace-symbols.js.map +1 -0
  365. package/dist/indexer/reference-candidates.d.ts.map +1 -1
  366. package/dist/indexer/reference-candidates.js +13 -7
  367. package/dist/indexer/reference-candidates.js.map +1 -1
  368. package/dist/indexer/reference-context.d.ts +2 -0
  369. package/dist/indexer/reference-context.d.ts.map +1 -1
  370. package/dist/indexer/reference-context.js +4 -0
  371. package/dist/indexer/reference-context.js.map +1 -1
  372. package/dist/indexer/scope-nodes.d.ts +92 -13
  373. package/dist/indexer/scope-nodes.d.ts.map +1 -1
  374. package/dist/indexer/scope-nodes.js +212 -20
  375. package/dist/indexer/scope-nodes.js.map +1 -1
  376. package/dist/indexer/scope-types.d.ts +29 -1
  377. package/dist/indexer/scope-types.d.ts.map +1 -1
  378. package/dist/indexer/scope.d.ts +2 -3
  379. package/dist/indexer/scope.d.ts.map +1 -1
  380. package/dist/indexer/scope.js +968 -47
  381. package/dist/indexer/scope.js.map +1 -1
  382. package/dist/indexer/shared-owner-identity.d.ts +53 -0
  383. package/dist/indexer/shared-owner-identity.d.ts.map +1 -0
  384. package/dist/indexer/shared-owner-identity.js +460 -0
  385. package/dist/indexer/shared-owner-identity.js.map +1 -0
  386. package/dist/indexer/shared.d.ts +1 -1
  387. package/dist/indexer/shared.d.ts.map +1 -1
  388. package/dist/indexer/shared.js +1 -1
  389. package/dist/indexer/shared.js.map +1 -1
  390. package/dist/indexer/star-import-precedence.d.ts +113 -0
  391. package/dist/indexer/star-import-precedence.d.ts.map +1 -0
  392. package/dist/indexer/star-import-precedence.js +402 -0
  393. package/dist/indexer/star-import-precedence.js.map +1 -0
  394. package/dist/indexer/symbols.d.ts +3 -1
  395. package/dist/indexer/symbols.d.ts.map +1 -1
  396. package/dist/indexer/symbols.js +58 -18
  397. package/dist/indexer/symbols.js.map +1 -1
  398. package/dist/indexer/ts-callables.d.ts +42 -0
  399. package/dist/indexer/ts-callables.d.ts.map +1 -0
  400. package/dist/indexer/ts-callables.js +233 -0
  401. package/dist/indexer/ts-callables.js.map +1 -0
  402. package/dist/indexer/types.d.ts +41 -26
  403. package/dist/indexer/types.d.ts.map +1 -1
  404. package/dist/indexer/unused-exports.d.ts +13 -0
  405. package/dist/indexer/unused-exports.d.ts.map +1 -0
  406. package/dist/indexer/unused-exports.js +159 -0
  407. package/dist/indexer/unused-exports.js.map +1 -0
  408. package/dist/indexer/workspace-symbols.d.ts.map +1 -1
  409. package/dist/indexer/workspace-symbols.js +3 -2
  410. package/dist/indexer/workspace-symbols.js.map +1 -1
  411. package/dist/indexer.d.ts +3 -8
  412. package/dist/indexer.d.ts.map +1 -1
  413. package/dist/indexer.js +1 -1
  414. package/dist/indexer.js.map +1 -1
  415. package/dist/languages/callable-arity.d.ts +223 -0
  416. package/dist/languages/callable-arity.d.ts.map +1 -0
  417. package/dist/languages/callable-arity.js +1199 -0
  418. package/dist/languages/callable-arity.js.map +1 -0
  419. package/dist/languages/definitions/c-family.d.ts.map +1 -1
  420. package/dist/languages/definitions/c-family.js +30 -1
  421. package/dist/languages/definitions/c-family.js.map +1 -1
  422. package/dist/languages/definitions/c.d.ts +4 -0
  423. package/dist/languages/definitions/c.d.ts.map +1 -1
  424. package/dist/languages/definitions/c.js +19 -0
  425. package/dist/languages/definitions/c.js.map +1 -1
  426. package/dist/languages/definitions/cpp.d.ts.map +1 -1
  427. package/dist/languages/definitions/cpp.js +12 -0
  428. package/dist/languages/definitions/cpp.js.map +1 -1
  429. package/dist/languages/definitions/csharp.d.ts.map +1 -1
  430. package/dist/languages/definitions/csharp.js +2 -8
  431. package/dist/languages/definitions/csharp.js.map +1 -1
  432. package/dist/languages/definitions/go.d.ts.map +1 -1
  433. package/dist/languages/definitions/go.js +3 -0
  434. package/dist/languages/definitions/go.js.map +1 -1
  435. package/dist/languages/definitions/javascript.d.ts.map +1 -1
  436. package/dist/languages/definitions/javascript.js +10 -1
  437. package/dist/languages/definitions/javascript.js.map +1 -1
  438. package/dist/languages/definitions/js-family.d.ts +1 -1
  439. package/dist/languages/definitions/js-family.d.ts.map +1 -1
  440. package/dist/languages/definitions/js-family.js +7 -1
  441. package/dist/languages/definitions/js-family.js.map +1 -1
  442. package/dist/languages/definitions/php.d.ts.map +1 -1
  443. package/dist/languages/definitions/php.js +5 -1
  444. package/dist/languages/definitions/php.js.map +1 -1
  445. package/dist/languages/definitions/typescript.d.ts.map +1 -1
  446. package/dist/languages/definitions/typescript.js +8 -1
  447. package/dist/languages/definitions/typescript.js.map +1 -1
  448. package/dist/languages/definitions/zig.d.ts.map +1 -1
  449. package/dist/languages/definitions/zig.js +8 -0
  450. package/dist/languages/definitions/zig.js.map +1 -1
  451. package/dist/lifecycle/manifest.d.ts.map +1 -1
  452. package/dist/lifecycle/manifest.js +0 -1
  453. package/dist/lifecycle/manifest.js.map +1 -1
  454. package/dist/mcp/handlers.js +14 -7
  455. package/dist/mcp/handlers.js.map +1 -1
  456. package/dist/native/byte-index.d.ts +6 -0
  457. package/dist/native/byte-index.d.ts.map +1 -1
  458. package/dist/native/byte-index.js +11 -6
  459. package/dist/native/byte-index.js.map +1 -1
  460. package/dist/native/contracts.d.ts +2 -3
  461. package/dist/native/contracts.d.ts.map +1 -1
  462. package/dist/native/execution.d.ts +9 -9
  463. package/dist/native/execution.d.ts.map +1 -1
  464. package/dist/native/execution.js +37 -77
  465. package/dist/native/execution.js.map +1 -1
  466. package/dist/native/js-bridge.d.ts +2 -15
  467. package/dist/native/js-bridge.d.ts.map +1 -1
  468. package/dist/native/js-bridge.js +2 -15
  469. package/dist/native/js-bridge.js.map +1 -1
  470. package/dist/native/query-results.js +2 -2
  471. package/dist/native/query-results.js.map +1 -1
  472. package/dist/native/runtime.d.ts +12 -12
  473. package/dist/native/runtime.d.ts.map +1 -1
  474. package/dist/native/runtime.js +24 -69
  475. package/dist/native/runtime.js.map +1 -1
  476. package/dist/native/tree-sitter-native.d.ts +3 -3
  477. package/dist/native/tree-sitter-native.d.ts.map +1 -1
  478. package/dist/native/tree-sitter-native.js +2 -2
  479. package/dist/native/tree-sitter-native.js.map +1 -1
  480. package/dist/presets.d.ts.map +1 -1
  481. package/dist/presets.js +0 -4
  482. package/dist/presets.js.map +1 -1
  483. package/dist/review/candidates.d.ts.map +1 -1
  484. package/dist/review/candidates.js +1 -1
  485. package/dist/review/candidates.js.map +1 -1
  486. package/dist/review/deleted.d.ts +3 -3
  487. package/dist/review/deleted.d.ts.map +1 -1
  488. package/dist/review/deleted.js +82 -32
  489. package/dist/review/deleted.js.map +1 -1
  490. package/dist/review/report.d.ts +1 -0
  491. package/dist/review/report.d.ts.map +1 -1
  492. package/dist/review/report.js +1 -1
  493. package/dist/review/report.js.map +1 -1
  494. package/dist/review.d.ts.map +1 -1
  495. package/dist/review.js +3 -20
  496. package/dist/review.js.map +1 -1
  497. package/dist/session.d.ts.map +1 -1
  498. package/dist/session.js +0 -5
  499. package/dist/session.js.map +1 -1
  500. package/dist/sql/navigation.d.ts.map +1 -1
  501. package/dist/sql/navigation.js +2 -1
  502. package/dist/sql/navigation.js.map +1 -1
  503. package/dist/sql/source-graph.d.ts.map +1 -1
  504. package/dist/sql/source-graph.js +2 -2
  505. package/dist/sql/source-graph.js.map +1 -1
  506. package/dist/sqlite/schema.d.ts +1 -1
  507. package/dist/sqlite/schema.d.ts.map +1 -1
  508. package/dist/sqlite/schema.js +8 -2
  509. package/dist/sqlite/schema.js.map +1 -1
  510. package/dist/sqlite/write.js +2 -2
  511. package/dist/sqlite/write.js.map +1 -1
  512. package/dist/types.d.ts +2 -0
  513. package/dist/types.d.ts.map +1 -1
  514. package/dist/util/bloom-filter.d.ts +8 -1
  515. package/dist/util/bloom-filter.d.ts.map +1 -1
  516. package/dist/util/bloom-filter.js +15 -2
  517. package/dist/util/bloom-filter.js.map +1 -1
  518. package/dist/util/glob.d.ts +32 -0
  519. package/dist/util/glob.d.ts.map +1 -0
  520. package/dist/util/glob.js +137 -0
  521. package/dist/util/glob.js.map +1 -0
  522. package/dist/util/graph-edges.d.ts +19 -1
  523. package/dist/util/graph-edges.d.ts.map +1 -1
  524. package/dist/util/graph-edges.js +30 -4
  525. package/dist/util/graph-edges.js.map +1 -1
  526. package/dist/util/identifiers.d.ts +15 -0
  527. package/dist/util/identifiers.d.ts.map +1 -1
  528. package/dist/util/identifiers.js +35 -0
  529. package/dist/util/identifiers.js.map +1 -1
  530. package/dist/util/member-access-tables.d.ts +61 -4
  531. package/dist/util/member-access-tables.d.ts.map +1 -1
  532. package/dist/util/member-access-tables.js +139 -19
  533. package/dist/util/member-access-tables.js.map +1 -1
  534. package/dist/util/member-access.d.ts +17 -0
  535. package/dist/util/member-access.d.ts.map +1 -1
  536. package/dist/util/member-access.js +98 -3
  537. package/dist/util/member-access.js.map +1 -1
  538. package/dist/util/project-files.d.ts +2 -10
  539. package/dist/util/project-files.d.ts.map +1 -1
  540. package/dist/util/project-files.js +29 -51
  541. package/dist/util/project-files.js.map +1 -1
  542. package/dist/util/python-type-checking.d.ts +18 -0
  543. package/dist/util/python-type-checking.d.ts.map +1 -0
  544. package/dist/util/python-type-checking.js +160 -0
  545. package/dist/util/python-type-checking.js.map +1 -0
  546. package/dist/util/resolution/cargo-targets.d.ts +11 -0
  547. package/dist/util/resolution/cargo-targets.d.ts.map +1 -1
  548. package/dist/util/resolution/cargo-targets.js +174 -13
  549. package/dist/util/resolution/cargo-targets.js.map +1 -1
  550. package/dist/util/resolution/csharp.d.ts +33 -1
  551. package/dist/util/resolution/csharp.d.ts.map +1 -1
  552. package/dist/util/resolution/csharp.js +145 -30
  553. package/dist/util/resolution/csharp.js.map +1 -1
  554. package/dist/util/resolution/jvm.d.ts +7 -3
  555. package/dist/util/resolution/jvm.d.ts.map +1 -1
  556. package/dist/util/resolution/jvm.js +56 -38
  557. package/dist/util/resolution/jvm.js.map +1 -1
  558. package/dist/util/resolution/php.d.ts.map +1 -1
  559. package/dist/util/resolution/php.js +35 -8
  560. package/dist/util/resolution/php.js.map +1 -1
  561. package/dist/util/resolution/python.d.ts +9 -0
  562. package/dist/util/resolution/python.d.ts.map +1 -1
  563. package/dist/util/resolution/python.js +46 -0
  564. package/dist/util/resolution/python.js.map +1 -1
  565. package/dist/util/resolution/rust.d.ts +0 -1
  566. package/dist/util/resolution/rust.d.ts.map +1 -1
  567. package/dist/util/resolution/rust.js +95 -35
  568. package/dist/util/resolution/rust.js.map +1 -1
  569. package/dist/util/resolution/specifier-targets.d.ts +44 -0
  570. package/dist/util/resolution/specifier-targets.d.ts.map +1 -0
  571. package/dist/util/resolution/specifier-targets.js +152 -0
  572. package/dist/util/resolution/specifier-targets.js.map +1 -0
  573. package/dist/util/resolution-candidates.d.ts +5 -0
  574. package/dist/util/resolution-candidates.d.ts.map +1 -1
  575. package/dist/util/resolution-candidates.js +16 -3
  576. package/dist/util/resolution-candidates.js.map +1 -1
  577. package/dist/util/resolution.d.ts +2 -1
  578. package/dist/util/resolution.d.ts.map +1 -1
  579. package/dist/util/resolution.js +101 -15
  580. package/dist/util/resolution.js.map +1 -1
  581. package/dist/util/specifiers.d.ts +29 -1
  582. package/dist/util/specifiers.d.ts.map +1 -1
  583. package/dist/util/specifiers.js +56 -8
  584. package/dist/util/specifiers.js.map +1 -1
  585. package/dist/util/trivia.d.ts.map +1 -1
  586. package/dist/util/trivia.js +49 -30
  587. package/dist/util/trivia.js.map +1 -1
  588. package/dist/util/workspace.d.ts.map +1 -1
  589. package/dist/util/workspace.js +32 -4
  590. package/dist/util/workspace.js.map +1 -1
  591. package/docs/mcp.md +3 -2
  592. package/package.json +5 -7
  593. package/dist/impact/call-compatibility/providers/profiles.d.ts +0 -80
  594. package/dist/impact/call-compatibility/providers/profiles.d.ts.map +0 -1
  595. package/dist/impact/call-compatibility/providers/profiles.js +0 -164
  596. package/dist/impact/call-compatibility/providers/profiles.js.map +0 -1
@@ -1,16 +1,60 @@
1
+ import path from "node:path";
1
2
  import { supportForFileWithoutHeaderSample } from "../languages.js";
2
- import { fileIdentityKey } from "../util/paths.js";
3
+ import { fileIdentityKey, normalizePath } from "../util/paths.js";
3
4
  import { sliceText, toRange } from "../util/ast.js";
5
+ import { getMemberAccessParts, isMemberAccessNode, isReceiverNameNode } from "../util/member-access.js";
6
+ import { classifyReceiver, declaresMembers, receiverConstructorExpression, } from "../graphs/symbol-graph-detailed/receiver-calls.js";
7
+ import { provenClassifiedReceiverOmitsMember } from "./navigation-goto.js";
4
8
  import { ensureParsedContext } from "./parse-context.js";
5
- import { sameDef } from "./reference-context.js";
6
- import { readPhpNamespaceFromRange } from "./navigation-php.js";
9
+ import { definitionIdentityKey, sameDef } from "./reference-context.js";
10
+ import { canonicalPhpReferenceNames, comparePhpReferenceNames, getPhpQualifiedReference, inferPhpQualifiedReferenceImportType, isInsidePhpUseDeclaration, isPhpQualifiedReferenceNode, phpLastIdentifierSegment, readPhpNamespaceFromRange, selectFirstExistingPhpCanonicalName, } from "./navigation-php.js";
11
+ import { isKeywordReceiver, memberSyntaxNamesFreeFunction } from "../util/member-access-tables.js";
12
+ import { getCompilationUnitPeers, getPackageDeclarationName } from "./compilation-units.js";
13
+ import { isJvmPackageSymbolVisible } from "./declaration-visibility.js";
14
+ import { findClosestScopeBinding, getOrBuildScopeIndex } from "./navigation-local.js";
15
+ import { scopeNodesFor } from "./scope-nodes.js";
7
16
  import { candidateFilesImportingTarget } from "./reference-candidates.js";
8
- import { buildScopeIndexFromSource } from "./scope.js";
9
- import { resolveExport, resolveImported } from "./navigation-resolve.js";
10
- import { ECMASCRIPT_IDENTIFIER_SOURCE } from "../util/identifiers.js";
17
+ import { bindingKindToSymbolKind } from "./declarations.js";
18
+ import { javaKotlinFunctionOverloadIncludes, javaStaticNamedImportIncludes, resolveExport, resolveImported, } from "./navigation-resolve.js";
19
+ import { isAmbiguousResolutionReason } from "./ambiguous-resolution.js";
20
+ import { ensurePhpNamespaceSymbolIndex, phpNamespaceSymbolIndexFor, phpReferenceRoleMatchesKind, } from "./php-namespace-symbols.js";
21
+ import { SymbolKind, } from "./types.js";
22
+ import { ECMASCRIPT_IDENTIFIER_SOURCE, foldPhpIdentifierCase } from "../util/identifiers.js";
23
+ import { JAVA_UNICODE_ESCAPE_BLOOM_TOKEN } from "../util/bloom-filter.js";
11
24
  const EXPORT_FROM_PATTERN = new RegExp(String.raw `\bexport\s+(?:type\s+)?\{([^}]*)\}\s*from\s*(["'])([^"']+)\2`, "gu");
12
25
  const NAMESPACE_EXPORT_PATTERN = new RegExp(String.raw `\bexport\s*\*\s*as\s*(${ECMASCRIPT_IDENTIFIER_SOURCE})\s*from\s*(["'])([^"']+)\2`, "gu");
13
26
  const EXPORT_FROM_SPECIFIER_PATTERN = new RegExp(String.raw `^(${ECMASCRIPT_IDENTIFIER_SOURCE})`, "u");
27
+ const importClosureCache = new WeakMap();
28
+ /** File keys reachable from `file` through resolved imports and includes, including `file`. */
29
+ function importClosure(index, file) {
30
+ let byFile = importClosureCache.get(index);
31
+ if (!byFile) {
32
+ byFile = new Map();
33
+ importClosureCache.set(index, byFile);
34
+ }
35
+ const startKey = fileIdentityKey(file);
36
+ const cached = byFile.get(startKey);
37
+ if (cached)
38
+ return cached;
39
+ const reached = new Set([startKey]);
40
+ const startModule = index.byFile.get(startKey);
41
+ const pending = startModule ? [startModule] : [];
42
+ while (pending.length) {
43
+ for (const imp of pending.pop().imports) {
44
+ if (typeof imp.resolved !== "string")
45
+ continue;
46
+ const key = fileIdentityKey(imp.resolved);
47
+ if (reached.has(key))
48
+ continue;
49
+ reached.add(key);
50
+ const moduleEntry = index.byFile.get(key);
51
+ if (moduleEntry)
52
+ pending.push(moduleEntry);
53
+ }
54
+ }
55
+ byFile.set(startKey, reached);
56
+ return reached;
57
+ }
14
58
  export function exportFromIdentifier(index, fileId, range, parsed) {
15
59
  if (!parsed.sup.supportsExportFromReferences)
16
60
  return null;
@@ -67,40 +111,198 @@ export function exportFromIdentifier(index, fileId, range, parsed) {
67
111
  return null;
68
112
  }
69
113
  export function getCachedScope(index, fileId, moduleIndex, parsedCtx) {
70
- const fileKey = fileIdentityKey(fileId);
71
- const cachedScope = index.scopeCache.get(fileKey);
72
- if (cachedScope) {
73
- for (const binding of cachedScope.all) {
74
- binding.occurrences = binding.occurrences.filter((occurrence) => !exportFromIdentifier(index, fileId, occurrence, parsedCtx)?.isExportFrom);
75
- }
76
- return cachedScope;
77
- }
78
- const scopeIndex = buildScopeIndexFromSource(fileId, parsedCtx.source, parsedCtx.sup, moduleIndex.imports, {
79
- tree: parsedCtx.tree,
80
- });
114
+ const keepOccurrence = (binding, occurrence) => {
115
+ if (exportFromIdentifier(index, fileId, occurrence, parsedCtx)?.isExportFrom)
116
+ return false;
117
+ if (parsedCtx.sup.id !== "php" || !binding.def || occurrence.start.index === binding.def.start.index)
118
+ return true;
119
+ const kind = bindingKindToSymbolKind(binding.kind);
120
+ if (kind === SymbolKind.Variable)
121
+ return true;
122
+ const start = occurrence.start.index;
123
+ if (start === undefined)
124
+ return true;
125
+ const node = parsedCtx.tree.rootNode.descendantForIndex(start, start);
126
+ return phpReferenceRoleMatchesKind(node, kind);
127
+ };
128
+ // One builder for the shared scope cache: it reuses the module's indexed callables.
129
+ const scopeIndex = getOrBuildScopeIndex(index, fileId, parsedCtx.source, parsedCtx.sup, moduleIndex, parsedCtx.tree);
81
130
  for (const binding of scopeIndex.all) {
82
- binding.occurrences = binding.occurrences.filter((occurrence) => !exportFromIdentifier(index, fileId, occurrence, parsedCtx)?.isExportFrom);
131
+ binding.occurrences = binding.occurrences.filter((occurrence) => keepOccurrence(binding, occurrence));
83
132
  }
84
- index.scopeCache.set(fileKey, scopeIndex);
85
133
  return scopeIndex;
86
134
  }
87
- export async function buildPhpQualifiedNames(index, definitionFile, def) {
135
+ /**
136
+ * The authoritative PHP spellings of a definition: `Namespace\Name`, or the bare `Name` for a
137
+ * global-namespace declaration. These are the names a reference must resolve to, so they keep
138
+ * the declaration's own case. A global-namespace declaration is still addressable by its bare
139
+ * name and by the fully-qualified `\Name` spelling, so the global-name scan must run for it;
140
+ * returning `[]` here left a global PHP symbol on the importer-narrowed path, which never scans
141
+ * a consumer that has no `use` statement.
142
+ */
143
+ async function readPhpDefinitionNames(index, definitionFile, def) {
88
144
  try {
89
145
  const definitionParsed = await ensureParsedContext(definitionFile, index.parsed?.get(fileIdentityKey(definitionFile)), index.languageExtensions);
90
146
  if (definitionParsed.sup.id !== "php") {
91
147
  return [];
92
148
  }
93
149
  const phpNamespace = readPhpNamespaceFromRange(definitionParsed.tree, definitionParsed.source, def.range);
94
- if (!phpNamespace)
95
- return [];
96
- const qualifiedName = `${phpNamespace}\\${def.localName}`;
97
- return [qualifiedName, `\\${qualifiedName}`];
150
+ return [phpNamespace ? `${phpNamespace}\\${def.localName}` : def.localName];
98
151
  }
99
152
  catch {
100
153
  return [];
101
154
  }
102
155
  }
103
- async function collectNamedNodeReferences(index, fileId, symbolName) {
156
+ export async function buildPhpQualifiedNames(index, definitionFile, def) {
157
+ // Keep one canonical spelling. Case-variant consumers are admitted during the single AST
158
+ // walk by comparePhpReferenceNames; extra folded probes would multiply whole-file scans.
159
+ return readPhpDefinitionNames(index, definitionFile, def);
160
+ }
161
+ const phpCanonicalNamesCache = new WeakMap();
162
+ const phpNameEquivalenceGaps = new WeakMap();
163
+ async function phpCanonicalDefinitionNames(index, def) {
164
+ let perIndex = phpCanonicalNamesCache.get(index);
165
+ if (!perIndex) {
166
+ perIndex = new Map();
167
+ phpCanonicalNamesCache.set(index, perIndex);
168
+ }
169
+ const key = definitionIdentityKey(def);
170
+ const cached = perIndex.get(key);
171
+ if (cached)
172
+ return cached;
173
+ const indexed = phpNamespaceSymbolIndexFor(index)?.canonicalByDefinition.get(key);
174
+ if (indexed) {
175
+ perIndex.set(key, [indexed]);
176
+ return [indexed];
177
+ }
178
+ const canonicalNames = (await readPhpDefinitionNames(index, def.file, def)).map((name) => name.replace(/^\\+/, ""));
179
+ perIndex.set(key, canonicalNames);
180
+ return canonicalNames;
181
+ }
182
+ function markPhpNameEquivalenceGap(index, def) {
183
+ let gaps = phpNameEquivalenceGaps.get(index);
184
+ if (!gaps) {
185
+ gaps = new Set();
186
+ phpNameEquivalenceGaps.set(index, gaps);
187
+ }
188
+ gaps.add(definitionIdentityKey(def));
189
+ }
190
+ const PHP_OWN_RECEIVER_KEYWORDS = new Set(["$this", "self", "static"]);
191
+ const PHP_TYPE_CONTAINER_TYPES = new Set([
192
+ "class_declaration",
193
+ "interface_declaration",
194
+ "trait_declaration",
195
+ "enum_declaration",
196
+ ]);
197
+ async function phpOwnerInfo(index, def) {
198
+ const module = index.byFile.get(fileIdentityKey(def.file));
199
+ if (!module)
200
+ return null;
201
+ const parsed = await ensureParsedContext(def.file, index.parsed?.get(fileIdentityKey(def.file)), index.languageExtensions);
202
+ const start = def.range.start;
203
+ const position = { row: Math.max(0, start.line - 1), column: Math.max(0, start.column - 1) };
204
+ let current = parsed.tree.rootNode.descendantForPosition(position, position);
205
+ while (current) {
206
+ if (PHP_TYPE_CONTAINER_TYPES.has(current.type)) {
207
+ const nameNode = current.childForFieldName("name");
208
+ const className = nameNode ? sliceText(nameNode, parsed.source) : null;
209
+ if (!className)
210
+ return null;
211
+ const owner = module.locals.find((local) => local.localName === className &&
212
+ local.range.start.index === nameNode?.startIndex &&
213
+ (local.kind === SymbolKind.Class ||
214
+ local.kind === SymbolKind.Interface ||
215
+ local.kind === SymbolKind.TypeAlias)) ?? null;
216
+ if (!owner)
217
+ return null;
218
+ return { owner, containerStart: current.startIndex, containerEnd: current.endIndex };
219
+ }
220
+ current = current.parent;
221
+ }
222
+ return null;
223
+ }
224
+ function phpMemberAccessProperty(node, parsed) {
225
+ const parent = node.parent;
226
+ if (!parent || !isMemberAccessNode(parsed.sup, parent))
227
+ return null;
228
+ const parts = getMemberAccessParts(parsed.sup, parent);
229
+ if (!parts.property || !parts.object)
230
+ return null;
231
+ const isProperty = parts.property === node ||
232
+ (parts.property.id !== undefined && parts.property.id === node.id) ||
233
+ (parts.property.startIndex === node.startIndex && parts.property.endIndex === node.endIndex);
234
+ if (!isProperty)
235
+ return null;
236
+ if (parts.object.startIndex === parts.property.startIndex)
237
+ return null;
238
+ return { object: parts.object, property: parts.property, parent };
239
+ }
240
+ async function phpCaseInsensitiveReceiverMemberMatch(index, fileId, node, parsed, expectedDef) {
241
+ const access = phpMemberAccessProperty(node, parsed);
242
+ if (!access)
243
+ return "skip";
244
+ const propertyText = sliceText(access.property, parsed.source);
245
+ const comparison = comparePhpReferenceNames(propertyText, expectedDef.localName, {
246
+ symbolKind: expectedDef.kind,
247
+ });
248
+ if (comparison !== "equivalent")
249
+ return "skip";
250
+ const exactSpelling = propertyText === expectedDef.localName;
251
+ const ownerInfo = await phpOwnerInfo(index, expectedDef);
252
+ if (!ownerInfo)
253
+ return exactSpelling ? "skip" : "unverified";
254
+ const owner = ownerInfo.owner;
255
+ const receiverName = sliceText(access.object, parsed.source);
256
+ if (PHP_OWN_RECEIVER_KEYWORDS.has(receiverName)) {
257
+ if (fileIdentityKey(fileId) === fileIdentityKey(expectedDef.file) &&
258
+ node.startIndex >= ownerInfo.containerStart &&
259
+ node.startIndex <= ownerInfo.containerEnd) {
260
+ return "matched";
261
+ }
262
+ return exactSpelling ? "skip" : "unverified";
263
+ }
264
+ if (isKeywordReceiver(parsed.sup.id, receiverName)) {
265
+ return exactSpelling ? "skip" : "unverified";
266
+ }
267
+ const constructor = receiverConstructorExpression(access.object, parsed.source, parsed.sup);
268
+ const typeNode = constructor ?? (access.parent.type === "scoped_call_expression" ? access.object : null);
269
+ if (!typeNode)
270
+ return exactSpelling ? "skip" : "unverified";
271
+ const ownerNames = await phpCanonicalDefinitionNames(index, owner);
272
+ const imports = index.byFile.get(fileIdentityKey(fileId))?.imports;
273
+ const typeNames = canonicalPhpReferenceNames(sliceText(typeNode, parsed.source), parsed.source, parsed.tree, typeNode, {
274
+ ...(imports ? { imports } : {}),
275
+ role: "class",
276
+ });
277
+ const matchesOwner = typeNames.some((typeName) => ownerNames.some((ownerName) => comparePhpReferenceNames(typeName, ownerName, { symbolKind: SymbolKind.Class }) === "equivalent"));
278
+ if (matchesOwner)
279
+ return "matched";
280
+ return "skip";
281
+ }
282
+ function matchesPhpFallbackDefinition(node, parsed, expectedDef) {
283
+ if (expectedDef.isMember)
284
+ return false;
285
+ const parent = node.parent;
286
+ if (parent && isMemberAccessNode(parsed.sup, parent)) {
287
+ const property = getMemberAccessParts(parsed.sup, parent).property;
288
+ if (property &&
289
+ (property === node ||
290
+ (property.id !== undefined && property.id === node.id) ||
291
+ (property.startIndex === node.startIndex && property.endIndex === node.endIndex))) {
292
+ return false;
293
+ }
294
+ }
295
+ const referenceKind = inferPhpQualifiedReferenceImportType(node);
296
+ if (expectedDef.kind === SymbolKind.Function)
297
+ return referenceKind === "function";
298
+ if (expectedDef.kind === SymbolKind.Class ||
299
+ expectedDef.kind === SymbolKind.Interface ||
300
+ expectedDef.kind === SymbolKind.TypeAlias) {
301
+ return referenceKind === "class";
302
+ }
303
+ return false;
304
+ }
305
+ async function collectNamedNodeReferences(index, fileId, symbolName, symbolKind) {
104
306
  try {
105
307
  const parsedEntry = index.parsed?.get(fileIdentityKey(fileId));
106
308
  const parsed = await ensureParsedContext(fileId, parsedEntry, index.languageExtensions);
@@ -112,15 +314,39 @@ async function collectNamedNodeReferences(index, fileId, symbolName) {
112
314
  "field_identifier",
113
315
  ]);
114
316
  const canonicalSymbolName = parsed.sup.normalizeIdentifier(symbolName);
115
- const ranges = [];
317
+ const isPhp = parsed.sup.id === "php";
318
+ const matched = [];
319
+ let nameEquivalenceUnavailable = false;
116
320
  const moduleIndex = index.byFile.get(fileIdentityKey(fileId));
117
321
  const importDeclarationKeys = importBindingDeclarationRangeKeys(moduleIndex);
322
+ const row = scopeNodesFor(parsed.sup.id);
118
323
  const walk = (node) => {
119
- if (identifierTypes.has(node.type) &&
120
- parsed.sup.normalizeIdentifier(sliceText(node, parsed.source)) === canonicalSymbolName) {
121
- const range = toRange(node);
122
- if (!importDeclarationKeys.has(rangeIdentityKey(range))) {
123
- ranges.push(range);
324
+ if (identifierTypes.has(node.type)) {
325
+ const text = parsed.sup.normalizeIdentifier(sliceText(node, parsed.source));
326
+ let isMatch;
327
+ if (!isPhp) {
328
+ isMatch = text === canonicalSymbolName;
329
+ }
330
+ else if ((node.type === "name" || node.type === "namespace_name") &&
331
+ (isPhpQualifiedReferenceNode(node.parent) ||
332
+ (node.parent && identifierTypes.has(node.parent.type) && row.childSkipNameTypes?.has(node.type)))) {
333
+ isMatch = false;
334
+ }
335
+ else {
336
+ const comparisonText = node.type === "qualified_name" || node.type === "relative_name" ? phpLastIdentifierSegment(text) : text;
337
+ const comparison = comparePhpReferenceNames(comparisonText, phpLastIdentifierSegment(canonicalSymbolName), {
338
+ caseSensitiveForm: node.type === "variable_name" || node.type === "constant",
339
+ ...(symbolKind ? { symbolKind } : {}),
340
+ });
341
+ if (comparison === "unverified")
342
+ nameEquivalenceUnavailable = true;
343
+ isMatch = comparison === "equivalent";
344
+ }
345
+ if (isMatch) {
346
+ const range = toRange(node);
347
+ if (!importDeclarationKeys.has(rangeIdentityKey(range)) && !(isPhp && isInsidePhpUseDeclaration(node))) {
348
+ matched.push({ range, node });
349
+ }
124
350
  }
125
351
  }
126
352
  for (const child of node.namedChildren) {
@@ -128,31 +354,149 @@ async function collectNamedNodeReferences(index, fileId, symbolName) {
128
354
  }
129
355
  };
130
356
  walk(parsed.tree.rootNode);
131
- return { ranges, parsed };
357
+ return { matched, parsed, nameEquivalenceUnavailable };
132
358
  }
133
359
  catch {
134
360
  return null;
135
361
  }
136
362
  }
137
- export async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, expectedDef, resolveDefinition, maxVerified, includeReference) {
138
- const collected = await collectNamedNodeReferences(index, fileId, symbolName);
363
+ /** True when `range` is the property of a member-access expression, not a bare call. */
364
+ export function isMemberAccessPropertyRange(parsed, range) {
365
+ const startIndex = range.start.index;
366
+ const node = startIndex !== undefined
367
+ ? parsed.tree.rootNode.descendantForIndex(startIndex, range.end.index ?? startIndex)
368
+ : parsed.tree.rootNode.descendantForPosition({ row: range.start.line - 1, column: range.start.column - 1 }, { row: range.start.line - 1, column: range.start.column - 1 });
369
+ const parent = node.parent;
370
+ if (!parent || !isMemberAccessNode(parsed.sup, parent))
371
+ return false;
372
+ const property = getMemberAccessParts(parsed.sup, parent).property;
373
+ return !!property && node.startIndex >= property.startIndex && node.endIndex <= property.endIndex;
374
+ }
375
+ /**
376
+ * A member call on a local, parameter, field, or `this`/`self` cannot name a free function
377
+ * in a language whose member syntax never calls one. A missing receiver, or a module or
378
+ * namespace binding (`util.helper()`, `mod.thing()`), stays unproven.
379
+ */
380
+ function freeFunctionMemberSiteIsProvenNonReference(index, fileId, parsed, objectNode, expectedDef) {
381
+ if (expectedDef.isMember || expectedDef.kind !== SymbolKind.Function)
382
+ return false;
383
+ if (memberSyntaxNamesFreeFunction(parsed.sup.id))
384
+ return false;
385
+ const receiverText = sliceText(objectNode, parsed.source).trim();
386
+ if (isKeywordReceiver(parsed.sup.id, receiverText))
387
+ return true;
388
+ if (!isReceiverNameNode(parsed.sup, objectNode.type))
389
+ return false;
390
+ const mod = index.byFile.get(fileIdentityKey(fileId));
391
+ if (!mod)
392
+ return false;
393
+ const binding = findClosestScopeBinding(getCachedScope(index, fileId, mod, parsed), receiverText, objectNode, parsed.sup);
394
+ return binding?.kind === "local" || binding?.kind === "param";
395
+ }
396
+ async function receiverProofUnavailable(index, fileId, parsed, range, resolveDefinition, expectedDef) {
397
+ const position = {
398
+ row: range.start.line - 1,
399
+ column: range.start.column - 1,
400
+ };
401
+ const nameNode = parsed.tree.rootNode.descendantForPosition(position, position);
402
+ let current = nameNode.parent;
403
+ while (current) {
404
+ if (isMemberAccessNode(parsed.sup, current)) {
405
+ const { object, property } = getMemberAccessParts(parsed.sup, current);
406
+ if (!object || !property || property.startIndex !== range.start.index)
407
+ return false;
408
+ const receiver = classifyReceiver(parsed.sup, object, parsed.source, new Map(), current.startIndex, current, (callee) => {
409
+ const mod = index.byFile.get(fileIdentityKey(fileId));
410
+ if (!mod)
411
+ return true;
412
+ const scope = getCachedScope(index, fileId, mod, parsed);
413
+ return !!findClosestScopeBinding(scope, sliceText(callee, parsed.source), callee, parsed.sup);
414
+ });
415
+ // A recognized shape is not proof. Exclude it only when the type is a resolved
416
+ // member-declaring definition, every supertype resolves, and none declare this member.
417
+ let unavailable;
418
+ if (receiver) {
419
+ const omits = await provenClassifiedReceiverOmitsMember(index, fileId, parsed, current, object, sliceText(property, parsed.source));
420
+ unavailable = !omits;
421
+ }
422
+ else {
423
+ const receiverRange = toRange(object);
424
+ const resolvedReceiver = await resolveDefinition({
425
+ file: fileId,
426
+ line: receiverRange.start.line,
427
+ column: receiverRange.start.column,
428
+ }, parsed);
429
+ unavailable = !(resolvedReceiver.status === "ok" &&
430
+ resolvedReceiver.definition &&
431
+ declaresMembers(resolvedReceiver.definition));
432
+ }
433
+ if (!unavailable)
434
+ return false;
435
+ return !freeFunctionMemberSiteIsProvenNonReference(index, fileId, parsed, object, expectedDef);
436
+ }
437
+ current = current.parent;
438
+ }
439
+ return false;
440
+ }
441
+ export async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, expectedDef, resolveDefinition, maxVerified, includeReference, onReceiverProofUnavailable, equivalentDefinitions = []) {
442
+ const collected = await collectNamedNodeReferences(index, fileId, symbolName, expectedDef.kind);
139
443
  if (!collected)
140
444
  return [];
141
- const { ranges, parsed } = collected;
445
+ const { matched, parsed, nameEquivalenceUnavailable } = collected;
446
+ if (nameEquivalenceUnavailable)
447
+ markPhpNameEquivalenceGap(index, expectedDef);
448
+ const phpCanonicalNames = parsed.sup.id === "php" ? await phpCanonicalDefinitionNames(index, expectedDef) : undefined;
449
+ const phpExistingFunctionNames = phpCanonicalNames && expectedDef.kind === SymbolKind.Function
450
+ ? (await ensurePhpNamespaceSymbolIndex(index)).functionNames
451
+ : undefined;
142
452
  const verified = [];
453
+ const matchesExpectedDefinition = (definition) => sameDef(definition, expectedDef, index.languageExtensions) ||
454
+ equivalentDefinitions.some((equivalent) => sameDef(definition, equivalent, index.languageExtensions));
455
+ const candidateFileKey = fileIdentityKey(fileId);
456
+ const equivalentDefinitionsInFile = equivalentDefinitions.filter((equivalent) => fileIdentityKey(equivalent.file) === candidateFileKey);
457
+ const isEquivalentDeclarationRange = (range) => equivalentDefinitionsInFile.some((equivalent) => {
458
+ const startMatches = range.start.index !== undefined && equivalent.range.start.index !== undefined
459
+ ? range.start.index === equivalent.range.start.index
460
+ : range.start.line === equivalent.range.start.line && range.start.column === equivalent.range.start.column;
461
+ const endMatches = range.end.index !== undefined && equivalent.range.end.index !== undefined
462
+ ? range.end.index === equivalent.range.end.index
463
+ : range.end.line === equivalent.range.end.line && range.end.column === equivalent.range.end.column;
464
+ return startMatches && endMatches;
465
+ });
143
466
  const pushVerified = (reference) => {
144
467
  if (!includeReference || includeReference(reference))
145
468
  verified.push(reference);
146
469
  };
147
- for (const range of ranges) {
470
+ let definitionVisible;
471
+ const definitionVisibleHere = () => {
472
+ if (definitionVisible === undefined) {
473
+ const closure = importClosure(index, fileId);
474
+ definitionVisible = [expectedDef, ...equivalentDefinitions].some((definition) => closure.has(fileIdentityKey(definition.file)));
475
+ }
476
+ return definitionVisible;
477
+ };
478
+ for (const { range, node } of matched) {
148
479
  if (maxVerified !== undefined && maxVerified > 0 && verified.length >= maxVerified) {
149
480
  break;
150
481
  }
482
+ if (isEquivalentDeclarationRange(range)) {
483
+ pushVerified({ range });
484
+ continue;
485
+ }
486
+ if (parsed.sup.id === "c" && expectedDef.kind === SymbolKind.Function) {
487
+ let enclosing = node.parent;
488
+ while (enclosing && enclosing.type !== "field_declaration" && enclosing.type !== "translation_unit") {
489
+ enclosing = enclosing.parent;
490
+ }
491
+ // A C struct function-pointer field is not a declaration or use of a free function.
492
+ if (enclosing?.type === "field_declaration")
493
+ continue;
494
+ }
151
495
  const exportFrom = exportFromIdentifier(index, fileId, range, parsed);
152
496
  if (exportFrom?.entry) {
153
497
  const reexported = resolveExport(index, exportFrom.entry.fromModule, exportFrom.entry.sourceSpecifier);
154
498
  if (reexported?.kind === "resolved") {
155
- if (sameDef(reexported.def, expectedDef, index.languageExtensions)) {
499
+ if (matchesExpectedDefinition(reexported.def)) {
156
500
  pushVerified({ range, via: { reexport: true } });
157
501
  }
158
502
  continue;
@@ -163,14 +507,71 @@ export async function collectVerifiedNamedNodeReferences(index, fileId, symbolNa
163
507
  line: range.start.line,
164
508
  column: range.start.column,
165
509
  }, parsed);
166
- if (resolved.status !== "ok" || !resolved.definition)
510
+ if (resolved.status === "ok" && resolved.definition) {
511
+ if (matchesExpectedDefinition(resolved.definition)) {
512
+ pushVerified({
513
+ range,
514
+ ...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}),
515
+ ...(resolved.provenance ? { provenance: resolved.provenance } : {}),
516
+ });
517
+ }
167
518
  continue;
168
- if (sameDef(resolved.definition, expectedDef, index.languageExtensions)) {
169
- pushVerified({
170
- range,
171
- ...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}),
172
- ...(resolved.provenance ? { provenance: resolved.provenance } : {}),
519
+ }
520
+ let recoveredByLanguageFallback = false;
521
+ if (parsed.sup.id === "php" && expectedDef.isMember) {
522
+ const memberMatch = await phpCaseInsensitiveReceiverMemberMatch(index, fileId, node, parsed, expectedDef);
523
+ if (memberMatch === "matched") {
524
+ pushVerified({ range, ...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}) });
525
+ recoveredByLanguageFallback = true;
526
+ }
527
+ else if (memberMatch === "unverified") {
528
+ markPhpNameEquivalenceGap(index, expectedDef);
529
+ }
530
+ }
531
+ else if (phpCanonicalNames && matchesPhpFallbackDefinition(node, parsed, expectedDef)) {
532
+ // PHP names are case-insensitive, but a namespace spelling alone cannot prove a member or
533
+ // distinguish a class reference from a function call. Restrict the fallback to syntax whose
534
+ // role matches the namespace-level definition.
535
+ const rawText = getPhpQualifiedReference(node, parsed.source) ?? sliceText(node, parsed.source);
536
+ const imports = index.byFile.get(fileIdentityKey(fileId))?.imports;
537
+ const role = inferPhpQualifiedReferenceImportType(node);
538
+ const candidates = canonicalPhpReferenceNames(rawText, parsed.source, parsed.tree, node, {
539
+ ...(imports ? { imports } : {}),
540
+ ...(role ? { role } : {}),
173
541
  });
542
+ const existingNames = phpExistingFunctionNames ?? phpCanonicalNames;
543
+ const selectedCandidate = selectFirstExistingPhpCanonicalName(candidates, existingNames, expectedDef.kind);
544
+ let matchedCanonical;
545
+ if (selectedCandidate) {
546
+ matchedCanonical = phpCanonicalNames.find((canonicalName) => comparePhpReferenceNames(selectedCandidate, canonicalName, { symbolKind: expectedDef.kind }) ===
547
+ "equivalent");
548
+ }
549
+ if (matchedCanonical) {
550
+ // A qualified path proves the namespace, but a bare case-variant `name` could also be a
551
+ // same-named constant, so the equivalence is unproven for that form and coverage says so
552
+ // instead of silently returning a short list.
553
+ if (!isPhpQualifiedReferenceNode(node)) {
554
+ const lastSegment = matchedCanonical.split("\\").pop() ?? matchedCanonical;
555
+ const bareText = sliceText(node, parsed.source).trim();
556
+ if (bareText !== lastSegment && foldPhpIdentifierCase(bareText) === foldPhpIdentifierCase(lastSegment)) {
557
+ markPhpNameEquivalenceGap(index, expectedDef);
558
+ }
559
+ }
560
+ pushVerified({ range, ...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}) });
561
+ recoveredByLanguageFallback = true;
562
+ }
563
+ }
564
+ // A same-name node that direct resolution and every language-specific fallback both failed
565
+ // to place is not provably unrelated: report the file so coverage cannot silently claim
566
+ // `complete` while this occurrence's status stays unknown. An ambiguous result (star
567
+ // imports, C++ overloads, or using targets) is the same kind of gap when this definition
568
+ // (or an equivalent declaration) is visible from this file: one of the candidates may be
569
+ // it. A name with no binding at all is proven unrelated by scope and stays out.
570
+ if (!recoveredByLanguageFallback && onReceiverProofUnavailable) {
571
+ if ((isAmbiguousResolutionReason(resolved.reason) && definitionVisibleHere()) ||
572
+ (await receiverProofUnavailable(index, fileId, parsed, range, resolveDefinition, expectedDef))) {
573
+ onReceiverProofUnavailable(fileId);
574
+ }
174
575
  }
175
576
  }
176
577
  return verified;
@@ -210,31 +611,81 @@ export function hasExpandedNamedImport(moduleIndex, targetFile, symbolName) {
210
611
  fileIdentityKey(candidate.resolved) === targetKey);
211
612
  }
212
613
  const referenceCandidateCache = new WeakMap();
614
+ /** A package import may expose a child only along its exact dotted module path. */
615
+ export function pythonParentPackageNamespacePaths(moduleIndex, definitionFile) {
616
+ const file = normalizePath(definitionFile);
617
+ const basename = path.posix.basename(file);
618
+ if (!file.endsWith(".py") && !file.endsWith(".pyi"))
619
+ return [];
620
+ const moduleStem = basename === "__init__.py" || basename === "__init__.pyi"
621
+ ? path.posix.dirname(file)
622
+ : file.slice(0, -path.posix.extname(file).length);
623
+ const paths = [];
624
+ for (const imp of moduleIndex.imports) {
625
+ if (imp.kind !== "namespace" || imp.mechanism !== "python" || typeof imp.resolved !== "string")
626
+ continue;
627
+ const target = normalizePath(imp.resolved);
628
+ const targetName = path.posix.basename(target);
629
+ const initializer = targetName === "__init__.py" || targetName === "__init__.pyi";
630
+ if (!initializer && (target.endsWith(".py") || target.endsWith(".pyi")))
631
+ continue;
632
+ const packageDirectory = initializer ? path.posix.dirname(target) : target;
633
+ const child = path.posix.relative(packageDirectory, moduleStem);
634
+ if (!child || child.startsWith("..") || path.posix.isAbsolute(child))
635
+ continue;
636
+ const boundName = imp.from.includes(".") && !imp.explicitAlias ? imp.from : imp.localNS;
637
+ paths.push({ namespace: boundName + "." + child.replaceAll("/", "."), importBinding: imp });
638
+ }
639
+ return paths;
640
+ }
213
641
  function referenceCandidateCacheKey(index, def, exportedNames) {
214
642
  const normalizeIdentifier = supportForFileWithoutHeaderSample(def.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
215
643
  const sortedNames = exportedNames.map(normalizeIdentifier).sort();
216
644
  return `${fileIdentityKey(def.file)}::${def.range.start.index ?? 0}::canonical::${sortedNames.join("\0")}`;
217
645
  }
218
- function importCanReferenceDefinition(index, imp, def, exportedNames) {
646
+ function importCanReferenceDefinition(index, imp, def, exportedNames, languageId) {
219
647
  const targetFile = typeof imp.resolved === "string" ? imp.resolved : undefined;
220
648
  if (!targetFile)
221
649
  return false;
650
+ let cNamespace;
651
+ if (languageId === "c")
652
+ cNamespace = def.cTag ? "tag" : "ordinary";
653
+ const exportOptions = cNamespace ? { cNamespace } : undefined;
654
+ if (cNamespace && imp.kind === "named" && (imp.cNamespace ?? "ordinary") !== cNamespace)
655
+ return false;
222
656
  const resolvesToDefinition = (exportedName) => {
223
- const hit = resolveExport(index, targetFile, exportedName);
657
+ const hit = resolveExport(index, targetFile, exportedName, exportOptions);
224
658
  if (hit?.kind === "resolved") {
225
659
  return sameDef(hit.def, def, index.languageExtensions);
226
660
  }
661
+ if (javaKotlinFunctionOverloadIncludes(index, targetFile, exportedName, def))
662
+ return true;
663
+ if (cppCanonicalStructuralExport(index, targetFile, exportedName, def, languageId)) {
664
+ return true;
665
+ }
227
666
  return imp.kind === "namespace" && fileIdentityKey(targetFile) === fileIdentityKey(def.file);
228
667
  };
229
668
  if (imp.kind === "named") {
230
- return resolvesToDefinition(imp.imported);
669
+ if (imp.jvmStaticWildcardName)
670
+ return javaStaticNamedImportIncludes(index, imp, def);
671
+ if (resolvesToDefinition(imp.imported))
672
+ return true;
673
+ // A python `from pkg import name` binds `name` from the package's own namespace; when the
674
+ // package has no such export, Python's own import system falls back to treating `name` as
675
+ // an implicit submodule attribute instead (the same fallback `resolveImported` applies at
676
+ // consumption time). Reusing that fallback here keeps candidate-file discovery in agreement
677
+ // with the goto/reference-collection consumers that already resolve through it.
678
+ if (languageId !== "python")
679
+ return false;
680
+ const result = resolveImported(index, imp, imp.imported, exportOptions);
681
+ return !!result && "namespace" in result && fileIdentityKey(result.namespace) === fileIdentityKey(def.file);
231
682
  }
232
683
  if (imp.kind === "default") {
233
684
  return resolvesToDefinition("default");
234
685
  }
235
686
  if (imp.kind === "star") {
236
687
  return exportedNames.some((exportedName) => {
237
- const result = resolveImported(index, imp, exportedName);
688
+ const result = resolveImported(index, imp, exportedName, exportOptions);
238
689
  return !!result && !("namespace" in result) && sameDef(result, def, index.languageExtensions);
239
690
  });
240
691
  }
@@ -259,10 +710,16 @@ function moduleExportProbeNames(index, moduleIndex, exportedNames, visited = new
259
710
  }
260
711
  return [...names];
261
712
  }
262
- function filesExportingDefinition(index, def, exportedNames) {
713
+ function filesExportingDefinition(index, def, exportedNames, languageId) {
263
714
  const files = new Map([[fileIdentityKey(def.file), def.file]]);
715
+ const namespaceLinks = [];
264
716
  for (const moduleIndex of index.byFile.values()) {
265
717
  const fileId = moduleIndex.file;
718
+ for (const entry of moduleIndex.exports) {
719
+ if (entry.type === "namespaceReexport") {
720
+ namespaceLinks.push({ sourceFile: fileId, exportedAs: entry.exportedAs, targetFile: entry.fromModule });
721
+ }
722
+ }
266
723
  if (fileIdentityKey(fileId) === fileIdentityKey(def.file) || !moduleIndex.exports.length)
267
724
  continue;
268
725
  for (const exportedName of moduleExportProbeNames(index, moduleIndex, exportedNames)) {
@@ -271,6 +728,10 @@ function filesExportingDefinition(index, def, exportedNames) {
271
728
  files.set(fileIdentityKey(fileId), fileId);
272
729
  break;
273
730
  }
731
+ if (cppCanonicalStructuralExport(index, fileId, exportedName, def, languageId)) {
732
+ files.set(fileIdentityKey(fileId), fileId);
733
+ break;
734
+ }
274
735
  }
275
736
  if (moduleIndex.exports.some((entry) => entry.type === "reexport" &&
276
737
  exportedNames.includes(entry.sourceSpecifier) &&
@@ -278,15 +739,31 @@ function filesExportingDefinition(index, def, exportedNames) {
278
739
  files.set(fileIdentityKey(fileId), fileId);
279
740
  }
280
741
  }
742
+ // A namespace re-export can expose an inner symbol through a member chain even
743
+ // though it does not export that symbol under its own name. Include consumers
744
+ // only when the visible namespace alias really targets the exporting module.
745
+ let grew = true;
746
+ while (grew) {
747
+ grew = false;
748
+ for (const link of namespaceLinks) {
749
+ const sourceKey = fileIdentityKey(link.sourceFile);
750
+ if (files.has(sourceKey) || !files.has(fileIdentityKey(link.targetFile)))
751
+ continue;
752
+ const visible = resolveExport(index, link.sourceFile, link.exportedAs, { allowLocalFallback: false });
753
+ if (visible?.kind !== "namespace" || fileIdentityKey(visible.file) !== fileIdentityKey(link.targetFile)) {
754
+ continue;
755
+ }
756
+ files.set(sourceKey, link.sourceFile);
757
+ grew = true;
758
+ }
759
+ }
281
760
  return [...files.values()];
282
761
  }
283
- function getIndexedReferenceCandidateFiles(index, def, exportedNames) {
284
- if (def.file.toLowerCase().endsWith(".php"))
285
- return undefined;
762
+ function getIndexedReferenceCandidateFiles(index, def, exportedNames, languageId) {
286
763
  if (!index.referenceCandidates)
287
764
  return undefined;
288
765
  const files = new Map();
289
- for (const exportingFile of filesExportingDefinition(index, def, exportedNames)) {
766
+ for (const exportingFile of filesExportingDefinition(index, def, exportedNames, languageId)) {
290
767
  for (const importingFile of candidateFilesImportingTarget(index.referenceCandidates, exportingFile) ?? []) {
291
768
  files.set(fileIdentityKey(importingFile), importingFile);
292
769
  }
@@ -295,30 +772,49 @@ function getIndexedReferenceCandidateFiles(index, def, exportedNames) {
295
772
  const fileId = moduleIndex.file;
296
773
  if (fileIdentityKey(fileId) === fileIdentityKey(def.file) || files.has(fileIdentityKey(fileId)))
297
774
  continue;
298
- if (moduleIndex.imports.some((imp) => (imp.kind === "star" || imp.kind === "namespace") &&
299
- importCanReferenceDefinition(index, imp, def, exportedNames))) {
775
+ if (moduleIndex.imports.some((imp) => (imp.kind === "star" || imp.kind === "namespace" || (imp.kind === "named" && imp.mechanism === "python")) &&
776
+ importCanReferenceDefinition(index, imp, def, exportedNames, languageId))) {
300
777
  files.set(fileIdentityKey(fileId), fileId);
301
778
  }
302
779
  }
303
780
  return [...files.values()].sort((left, right) => left.localeCompare(right));
304
781
  }
305
- export function getCachedReferenceCandidateFiles(index, def, exportedNames, hasGlobalNameReferences) {
782
+ export function getCachedReferenceCandidateFiles(index, def, exportedNames, hasGlobalNameReferences, languageId) {
306
783
  if (hasGlobalNameReferences) {
307
- return Array.from(index.byFile.values(), (module) => module.file).sort((left, right) => left.localeCompare(right));
784
+ // Callers only set this for a PHP definition (`buildPhpQualifiedNames` returns names for no
785
+ // other language), and PHP's global-namespace fallback can be referenced from any PHP file
786
+ // without an import, so the import-graph narrowing below cannot apply. Every other language
787
+ // is still a sound, source-free rejection: a PHP symbol can never be referenced from a file
788
+ // whose own language a different parser owns.
789
+ return Array.from(index.byFile.values(), (module) => module.file)
790
+ .filter((file) => supportForFileWithoutHeaderSample(file, index.languageExtensions)?.id === "php")
791
+ .sort((left, right) => left.localeCompare(right));
308
792
  }
309
793
  let cache = referenceCandidateCache.get(index);
310
794
  if (!cache) {
311
795
  cache = new Map();
312
796
  referenceCandidateCache.set(index, cache);
313
797
  }
314
- const key = referenceCandidateCacheKey(index, def, exportedNames);
798
+ const key = `${languageId}:${referenceCandidateCacheKey(index, def, exportedNames)}`;
315
799
  const cached = cache.get(key);
316
800
  if (cached)
317
801
  return cached;
318
802
  const candidates = new Map();
319
- const candidateFileEntries = getIndexedReferenceCandidateFiles(index, def, exportedNames) ??
803
+ if (def.isMember)
804
+ candidates.set(fileIdentityKey(def.file), def.file);
805
+ // Files sharing the definition's compilation unit can name it without any import edge (Go and
806
+ // JVM packages, C# namespaces, Swift modules), so they bypass the import filter below. C#
807
+ // also includes same-directory files that can reach the type only through a qualified name,
808
+ // so dotted and `global::` uses are candidates even when the consumer declares unrelated
809
+ // namespaces. Bare-name resolution still uses the related-namespace peer set.
810
+ for (const unitPeer of getCompilationUnitPeers(index, def.file, languageId === "csharp" ? { csharpQualifiedName: true } : undefined).files) {
811
+ if (fileIdentityKey(unitPeer) !== fileIdentityKey(def.file)) {
812
+ candidates.set(fileIdentityKey(unitPeer), unitPeer);
813
+ }
814
+ }
815
+ const candidateFileEntries = getIndexedReferenceCandidateFiles(index, def, exportedNames, languageId) ??
320
816
  Array.from(index.byFile.values(), (module) => module.file);
321
- const exportingFileIds = filesExportingDefinition(index, def, exportedNames);
817
+ const exportingFileIds = filesExportingDefinition(index, def, exportedNames, languageId);
322
818
  const exportingFiles = new Set(exportingFileIds.map((file) => fileIdentityKey(file)));
323
819
  for (const fileId of exportingFileIds) {
324
820
  if (fileIdentityKey(fileId) !== fileIdentityKey(def.file)) {
@@ -335,16 +831,94 @@ export function getCachedReferenceCandidateFiles(index, def, exportedNames, hasG
335
831
  if (typeof imp.resolved !== "string")
336
832
  return false;
337
833
  return (exportingFiles.has(fileIdentityKey(imp.resolved)) ||
338
- importCanReferenceDefinition(index, imp, def, exportedNames));
834
+ importCanReferenceDefinition(index, imp, def, exportedNames, languageId));
339
835
  })) {
340
836
  candidates.set(fileIdentityKey(fileId), fileId);
341
837
  }
342
838
  }
839
+ // A fully package-qualified use needs no import, even from another compilation unit.
840
+ // Probe both its package root and member name; Java Unicode escapes can hide either spelling.
841
+ if (languageId === "java" || languageId === "kotlin") {
842
+ const packageName = getPackageDeclarationName(index, def.file, languageId);
843
+ const rootName = packageName?.split(".")[0];
844
+ if (rootName) {
845
+ const exported = def.isMember ||
846
+ index.byFile
847
+ .get(fileIdentityKey(def.file))
848
+ ?.exports.some((entry) => entry.type === "local" && sameDef(entry.target, def, index.languageExtensions));
849
+ if (exported) {
850
+ for (const moduleIndex of index.byFile.values()) {
851
+ const support = supportForFileWithoutHeaderSample(moduleIndex.file, index.languageExtensions);
852
+ if (support?.id !== "java" && support?.id !== "kotlin")
853
+ continue;
854
+ const samePackage = getPackageDeclarationName(index, moduleIndex.file, support.id) === packageName;
855
+ if (!isJvmPackageSymbolVisible(def, languageId, support.id, samePackage))
856
+ continue;
857
+ const fileKey = fileIdentityKey(moduleIndex.file);
858
+ if (candidates.has(fileKey))
859
+ continue;
860
+ const filter = index.bloomFilters?.get(fileKey);
861
+ const rootProbe = support.normalizeIdentifier(rootName);
862
+ const nameProbe = support.normalizeIdentifier(def.localName);
863
+ if (!filter ||
864
+ (filter.mightContain(rootProbe) && filter.mightContain(nameProbe)) ||
865
+ (support.id === "java" && filter.mightContain(JAVA_UNICODE_ESCAPE_BLOOM_TOKEN))) {
866
+ candidates.set(fileKey, moduleIndex.file);
867
+ }
868
+ }
869
+ }
870
+ }
871
+ }
872
+ // A plain package import does not prove its child's attribute, but a same-name use
873
+ // through that package must be checked before coverage can claim completeness.
874
+ if (languageId === "python" && !def.isMember) {
875
+ for (const moduleIndex of index.byFile.values()) {
876
+ if (pythonParentPackageNamespacePaths(moduleIndex, def.file).length) {
877
+ candidates.set(fileIdentityKey(moduleIndex.file), moduleIndex.file);
878
+ }
879
+ }
880
+ }
343
881
  const sorted = [...candidates.values()].sort((left, right) => left.localeCompare(right));
344
882
  cache.set(key, sorted);
345
883
  return sorted;
346
884
  }
347
- const COVERAGE_REASON_ORDER = ["parser_degraded", "unresolved_import", "truncated"];
885
+ /**
886
+ * The single precedence table for reference-coverage reasons, shared by the direct
887
+ * indexed-candidate builder and the bounded reference lookup cache. Existing reasons keep
888
+ * their established relative order so current expectations stay stable; the two strategy
889
+ * reasons sit after the file-level reasons they refine and before `truncated`, because a
890
+ * skipped collection strategy is a correctness gap while `truncated` only reflects the
891
+ * caller's own requested bound.
892
+ */
893
+ export const REFERENCE_COVERAGE_REASON_ORDER = [
894
+ "parser_degraded",
895
+ "unresolved_import",
896
+ "strategy_unavailable",
897
+ "name_equivalence_unavailable",
898
+ "truncated",
899
+ ];
900
+ export function describeReferenceStrategies(args) {
901
+ const applicable = [];
902
+ const executed = [];
903
+ if (args.sameFileOccurrence?.applicable) {
904
+ applicable.push("same_file_occurrence");
905
+ if (args.sameFileOccurrence.executed)
906
+ executed.push("same_file_occurrence");
907
+ }
908
+ if (args.implicitUnitPeers?.applicable) {
909
+ applicable.push("implicit_unit_peers");
910
+ if (args.implicitUnitPeers.executed)
911
+ executed.push("implicit_unit_peers");
912
+ }
913
+ if (args.languageId === "php") {
914
+ // Every PHP definition is addressable by its global or namespace-qualified spelling, so
915
+ // the qualified-name scan is required; the receiver scan is not the PHP strategy.
916
+ applicable.push("php_qualified_name");
917
+ if (args.phpQualifiedNames.length)
918
+ executed.push("php_qualified_name");
919
+ }
920
+ return { applicable, executed };
921
+ }
348
922
  export function rangeIdentityKey(range) {
349
923
  return `${range.start.line}:${range.start.column}:${range.start.index ?? ""}:${range.end.line}:${range.end.column}:${range.end.index ?? ""}`;
350
924
  }
@@ -379,7 +953,7 @@ export function importBindingReferenceSites(imp) {
379
953
  sites.push({ range: localRange, importBinding: "local" });
380
954
  }
381
955
  }
382
- else if (imp.kind === "default") {
956
+ else if (imp.kind === "default" || imp.kind === "namespace") {
383
957
  const { localRange } = bindingTokenRanges(imp);
384
958
  if (localRange) {
385
959
  sites.push({ range: localRange, importBinding: "local" });
@@ -443,7 +1017,13 @@ function structurallyExportsDefinition(index, moduleFile, exportedName, def, def
443
1017
  }
444
1018
  return false;
445
1019
  }
446
- function isUnresolvedIndexedImport(index, imp, def, exportedNames) {
1020
+ /** Recover C++ overload candidates through real exports, never the unresolved-import name shortcut. */
1021
+ export function cppCanonicalStructuralExport(index, targetFile, exportedName, def, languageId) {
1022
+ if (languageId !== "cpp")
1023
+ return false;
1024
+ return structurallyExportsDefinition(index, targetFile, exportedName, def, []);
1025
+ }
1026
+ function isUnresolvedIndexedImport(index, imp, def, exportedNames, languageId) {
447
1027
  if (typeof imp.resolved !== "string")
448
1028
  return false;
449
1029
  let importedName;
@@ -455,7 +1035,7 @@ function isUnresolvedIndexedImport(index, imp, def, exportedNames) {
455
1035
  return false;
456
1036
  if (!structurallyExportsDefinition(index, imp.resolved, importedName, def, exportedNames))
457
1037
  return false;
458
- return !importCanReferenceDefinition(index, imp, def, exportedNames);
1038
+ return !importCanReferenceDefinition(index, imp, def, exportedNames, languageId);
459
1039
  }
460
1040
  function parserDegradedCandidateFiles(index, scannedFiles) {
461
1041
  const report = index.buildReport?.backend?.parser;
@@ -484,7 +1064,7 @@ function parserDegradedCandidateFiles(index, scannedFiles) {
484
1064
  return { files: affected, hasUnlistedCandidate };
485
1065
  }
486
1066
  export function buildIndexedCandidateCoverage(args) {
487
- const { index, def, exportedNames, candidateFiles, scannedFiles, truncated } = args;
1067
+ const { index, def, languageId, exportedNames, candidateFiles, scannedFiles, truncated, strategies, strategyUnavailableFiles = [], } = args;
488
1068
  const reasons = [];
489
1069
  const affectedFiles = [];
490
1070
  const affectedSeen = new Set();
@@ -506,7 +1086,7 @@ export function buildIndexedCandidateCoverage(args) {
506
1086
  const moduleIndex = index.byFile.get(fileIdentityKey(fileId));
507
1087
  if (!moduleIndex)
508
1088
  continue;
509
- if (moduleIndex.imports.some((imp) => isUnresolvedIndexedImport(index, imp, def, exportedNames))) {
1089
+ if (moduleIndex.imports.some((imp) => isUnresolvedIndexedImport(index, imp, def, exportedNames, languageId))) {
510
1090
  unresolvedFiles.push(fileId);
511
1091
  }
512
1092
  }
@@ -515,6 +1095,20 @@ export function buildIndexedCandidateCoverage(args) {
515
1095
  for (const file of unresolvedFiles)
516
1096
  addAffected(file);
517
1097
  }
1098
+ if (strategyUnavailableFiles.length) {
1099
+ reasons.push("strategy_unavailable");
1100
+ for (const file of strategyUnavailableFiles)
1101
+ addAffected(file);
1102
+ }
1103
+ if (strategies) {
1104
+ const executed = new Set(strategies.executed);
1105
+ if (strategies.applicable.some((strategy) => !executed.has(strategy))) {
1106
+ reasons.push("strategy_unavailable");
1107
+ }
1108
+ }
1109
+ if (phpNameEquivalenceGaps.get(index)?.has(definitionIdentityKey(def))) {
1110
+ reasons.push("name_equivalence_unavailable");
1111
+ }
518
1112
  if (truncated)
519
1113
  reasons.push("truncated");
520
1114
  if (!reasons.length) {
@@ -523,7 +1117,7 @@ export function buildIndexedCandidateCoverage(args) {
523
1117
  return {
524
1118
  scope: "indexed_candidates",
525
1119
  state: "partial",
526
- reasons: COVERAGE_REASON_ORDER.filter((reason) => reasons.includes(reason)),
1120
+ reasons: REFERENCE_COVERAGE_REASON_ORDER.filter((reason) => reasons.includes(reason)),
527
1121
  ...(affectedFiles.length ? { affectedFiles } : {}),
528
1122
  };
529
1123
  }