@lzehrung/codegraph 2.4.0 → 3.0.1

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 (452) hide show
  1. package/README.md +5 -4
  2. package/codegraph-skill/codegraph/SKILL.md +3 -3
  3. package/dist/agent/call-hierarchy.js +2 -4
  4. package/dist/agent/call-hierarchy.js.map +1 -1
  5. package/dist/agent/explore.d.ts +1 -1
  6. package/dist/agent/explore.d.ts.map +1 -1
  7. package/dist/agent/explore.js +3 -2
  8. package/dist/agent/explore.js.map +1 -1
  9. package/dist/agent/refactor-plan.js +2 -4
  10. package/dist/agent/refactor-plan.js.map +1 -1
  11. package/dist/agent/rename-preview.d.ts.map +1 -1
  12. package/dist/agent/rename-preview.js +58 -8
  13. package/dist/agent/rename-preview.js.map +1 -1
  14. package/dist/agent/search.js +2 -3
  15. package/dist/agent/search.js.map +1 -1
  16. package/dist/agent/semantic-symbols.d.ts.map +1 -1
  17. package/dist/agent/semantic-symbols.js +2 -3
  18. package/dist/agent/semantic-symbols.js.map +1 -1
  19. package/dist/agent/type-hierarchy.js +2 -4
  20. package/dist/agent/type-hierarchy.js.map +1 -1
  21. package/dist/agent/workspace-symbols.d.ts.map +1 -1
  22. package/dist/agent/workspace-symbols.js +2 -3
  23. package/dist/agent/workspace-symbols.js.map +1 -1
  24. package/dist/agent-tools.d.ts +0 -4
  25. package/dist/agent-tools.d.ts.map +1 -1
  26. package/dist/agent-tools.js +3 -6
  27. package/dist/agent-tools.js.map +1 -1
  28. package/dist/analysis-summary.d.ts +8 -4
  29. package/dist/analysis-summary.d.ts.map +1 -1
  30. package/dist/analysis-summary.js +15 -66
  31. package/dist/analysis-summary.js.map +1 -1
  32. package/dist/bin/cli.js +14417 -16886
  33. package/dist/bin/query-index-worker.js +229 -99
  34. package/dist/cli/command-table.d.ts.map +1 -1
  35. package/dist/cli/command-table.js +9 -17
  36. package/dist/cli/command-table.js.map +1 -1
  37. package/dist/cli/context.js +10 -10
  38. package/dist/cli/context.js.map +1 -1
  39. package/dist/cli/drift.d.ts +0 -2
  40. package/dist/cli/drift.d.ts.map +1 -1
  41. package/dist/cli/drift.js +0 -1
  42. package/dist/cli/drift.js.map +1 -1
  43. package/dist/cli/graph-delta.d.ts +0 -2
  44. package/dist/cli/graph-delta.d.ts.map +1 -1
  45. package/dist/cli/graph-delta.js +0 -4
  46. package/dist/cli/graph-delta.js.map +1 -1
  47. package/dist/cli/graph.d.ts +0 -3
  48. package/dist/cli/graph.d.ts.map +1 -1
  49. package/dist/cli/graph.js +4 -14
  50. package/dist/cli/graph.js.map +1 -1
  51. package/dist/cli/help.d.ts +34 -34
  52. package/dist/cli/help.d.ts.map +1 -1
  53. package/dist/cli/help.js +6 -13
  54. package/dist/cli/help.js.map +1 -1
  55. package/dist/cli/impact.d.ts +0 -2
  56. package/dist/cli/impact.d.ts.map +1 -1
  57. package/dist/cli/impact.js +0 -1
  58. package/dist/cli/impact.js.map +1 -1
  59. package/dist/cli/index.d.ts +0 -2
  60. package/dist/cli/index.d.ts.map +1 -1
  61. package/dist/cli/index.js +5 -6
  62. package/dist/cli/index.js.map +1 -1
  63. package/dist/cli/inspect.d.ts +0 -2
  64. package/dist/cli/inspect.d.ts.map +1 -1
  65. package/dist/cli/inspect.js +5 -8
  66. package/dist/cli/inspect.js.map +1 -1
  67. package/dist/cli/invocation-context.d.ts +0 -3
  68. package/dist/cli/invocation-context.d.ts.map +1 -1
  69. package/dist/cli/invocation-context.js +4 -16
  70. package/dist/cli/invocation-context.js.map +1 -1
  71. package/dist/cli/navigation.d.ts +0 -2
  72. package/dist/cli/navigation.d.ts.map +1 -1
  73. package/dist/cli/navigation.js +0 -1
  74. package/dist/cli/navigation.js.map +1 -1
  75. package/dist/cli/options.d.ts.map +1 -1
  76. package/dist/cli/options.js +2 -12
  77. package/dist/cli/options.js.map +1 -1
  78. package/dist/cli/review.d.ts +0 -2
  79. package/dist/cli/review.d.ts.map +1 -1
  80. package/dist/cli/review.js +0 -5
  81. package/dist/cli/review.js.map +1 -1
  82. package/dist/cli/root-policy.d.ts +0 -2
  83. package/dist/cli/root-policy.d.ts.map +1 -1
  84. package/dist/cli/root-policy.js +0 -8
  85. package/dist/cli/root-policy.js.map +1 -1
  86. package/dist/cli/server.d.ts.map +1 -1
  87. package/dist/cli/server.js +0 -2
  88. package/dist/cli/server.js.map +1 -1
  89. package/dist/drift/git.d.ts.map +1 -1
  90. package/dist/drift/git.js +0 -1
  91. package/dist/drift/git.js.map +1 -1
  92. package/dist/drift/snapshot.d.ts.map +1 -1
  93. package/dist/drift/snapshot.js +0 -1
  94. package/dist/drift/snapshot.js.map +1 -1
  95. package/dist/drift/types.d.ts +0 -2
  96. package/dist/drift/types.d.ts.map +1 -1
  97. package/dist/drift/types.js.map +1 -1
  98. package/dist/duplicates/unit-cache.d.ts +0 -1
  99. package/dist/duplicates/unit-cache.d.ts.map +1 -1
  100. package/dist/duplicates/unit-cache.js +3 -11
  101. package/dist/duplicates/unit-cache.js.map +1 -1
  102. package/dist/duplicates/units.d.ts +5 -5
  103. package/dist/duplicates/units.d.ts.map +1 -1
  104. package/dist/duplicates/units.js +25 -88
  105. package/dist/duplicates/units.js.map +1 -1
  106. package/dist/graph-builder.d.ts +0 -6
  107. package/dist/graph-builder.d.ts.map +1 -1
  108. package/dist/graph-builder.js +2 -5
  109. package/dist/graph-builder.js.map +1 -1
  110. package/dist/graph-edge-collector.d.ts +1 -6
  111. package/dist/graph-edge-collector.d.ts.map +1 -1
  112. package/dist/graph-edge-collector.js +23 -21
  113. package/dist/graph-edge-collector.js.map +1 -1
  114. package/dist/graphs/edge-resolution.d.ts +1 -1
  115. package/dist/graphs/edge-resolution.d.ts.map +1 -1
  116. package/dist/graphs/edge-resolution.js +22 -98
  117. package/dist/graphs/edge-resolution.js.map +1 -1
  118. package/dist/graphs/specifiers.d.ts +4 -13
  119. package/dist/graphs/specifiers.d.ts.map +1 -1
  120. package/dist/graphs/specifiers.js +76 -173
  121. package/dist/graphs/specifiers.js.map +1 -1
  122. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts +12 -3
  123. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
  124. package/dist/graphs/symbol-graph-detailed/edge-passes.js +315 -177
  125. package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
  126. package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts.map +1 -1
  127. package/dist/graphs/symbol-graph-detailed/import-aliases.js +11 -0
  128. package/dist/graphs/symbol-graph-detailed/import-aliases.js.map +1 -1
  129. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +25 -22
  130. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
  131. package/dist/graphs/symbol-graph-detailed/receiver-calls.js +216 -147
  132. package/dist/graphs/symbol-graph-detailed/receiver-calls.js.map +1 -1
  133. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  134. package/dist/graphs/symbol-graph-detailed.js +80 -71
  135. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  136. package/dist/graphs/symbol-graph.d.ts +1 -1
  137. package/dist/graphs/symbol-graph.d.ts.map +1 -1
  138. package/dist/graphs/symbol-graph.js +12 -4
  139. package/dist/graphs/symbol-graph.js.map +1 -1
  140. package/dist/graphs/types.d.ts +0 -4
  141. package/dist/graphs/types.d.ts.map +1 -1
  142. package/dist/graphs.d.ts +1 -1
  143. package/dist/graphs.d.ts.map +1 -1
  144. package/dist/impact/analyzer.d.ts.map +1 -1
  145. package/dist/impact/analyzer.js +94 -1
  146. package/dist/impact/analyzer.js.map +1 -1
  147. package/dist/impact/call-compatibility.d.ts.map +1 -1
  148. package/dist/impact/call-compatibility.js +39 -43
  149. package/dist/impact/call-compatibility.js.map +1 -1
  150. package/dist/impact/transitive.d.ts +6 -2
  151. package/dist/impact/transitive.d.ts.map +1 -1
  152. package/dist/impact/transitive.js +23 -11
  153. package/dist/impact/transitive.js.map +1 -1
  154. package/dist/index.d.ts +2 -2
  155. package/dist/index.d.ts.map +1 -1
  156. package/dist/index.js.map +1 -1
  157. package/dist/indexer/build-cache/module-cache.d.ts +1 -1
  158. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  159. package/dist/indexer/build-cache/module-cache.js +67 -12
  160. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  161. package/dist/indexer/build-cache/options.d.ts +17 -2
  162. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  163. package/dist/indexer/build-cache/options.js +19 -29
  164. package/dist/indexer/build-cache/options.js.map +1 -1
  165. package/dist/indexer/build-cache/project-snapshot.d.ts +3 -4
  166. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  167. package/dist/indexer/build-cache/project-snapshot.js +53 -62
  168. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  169. package/dist/indexer/build-cache/reports.d.ts +0 -2
  170. package/dist/indexer/build-cache/reports.d.ts.map +1 -1
  171. package/dist/indexer/build-cache/reports.js +0 -97
  172. package/dist/indexer/build-cache/reports.js.map +1 -1
  173. package/dist/indexer/build-cache.d.ts +1 -1
  174. package/dist/indexer/build-cache.d.ts.map +1 -1
  175. package/dist/indexer/build-cache.js +1 -1
  176. package/dist/indexer/build-cache.js.map +1 -1
  177. package/dist/indexer/build-index.d.ts.map +1 -1
  178. package/dist/indexer/build-index.js +72 -58
  179. package/dist/indexer/build-index.js.map +1 -1
  180. package/dist/indexer/build-workers.d.ts.map +1 -1
  181. package/dist/indexer/build-workers.js +9 -9
  182. package/dist/indexer/build-workers.js.map +1 -1
  183. package/dist/indexer/callable-identity.d.ts +24 -0
  184. package/dist/indexer/callable-identity.d.ts.map +1 -0
  185. package/dist/indexer/callable-identity.js +111 -0
  186. package/dist/indexer/callable-identity.js.map +1 -0
  187. package/dist/indexer/compilation-units.d.ts +2 -0
  188. package/dist/indexer/compilation-units.d.ts.map +1 -1
  189. package/dist/indexer/compilation-units.js +20 -18
  190. package/dist/indexer/compilation-units.js.map +1 -1
  191. package/dist/indexer/cpp-callables.d.ts +12 -7
  192. package/dist/indexer/cpp-callables.d.ts.map +1 -1
  193. package/dist/indexer/cpp-callables.js +42 -34
  194. package/dist/indexer/cpp-callables.js.map +1 -1
  195. package/dist/indexer/declaration-visibility.d.ts +7 -0
  196. package/dist/indexer/declaration-visibility.d.ts.map +1 -1
  197. package/dist/indexer/declaration-visibility.js +22 -0
  198. package/dist/indexer/declaration-visibility.js.map +1 -1
  199. package/dist/indexer/declarations.d.ts.map +1 -1
  200. package/dist/indexer/declarations.js +32 -7
  201. package/dist/indexer/declarations.js.map +1 -1
  202. package/dist/indexer/expand-star-imports.d.ts +6 -1
  203. package/dist/indexer/expand-star-imports.d.ts.map +1 -1
  204. package/dist/indexer/expand-star-imports.js +120 -48
  205. package/dist/indexer/expand-star-imports.js.map +1 -1
  206. package/dist/indexer/finalize.d.ts.map +1 -1
  207. package/dist/indexer/finalize.js +0 -1
  208. package/dist/indexer/finalize.js.map +1 -1
  209. package/dist/indexer/import-resolution-tables.d.ts +72 -0
  210. package/dist/indexer/import-resolution-tables.d.ts.map +1 -0
  211. package/dist/indexer/import-resolution-tables.js +147 -0
  212. package/dist/indexer/import-resolution-tables.js.map +1 -0
  213. package/dist/indexer/import-types.d.ts +18 -1
  214. package/dist/indexer/import-types.d.ts.map +1 -1
  215. package/dist/indexer/import-types.js.map +1 -1
  216. package/dist/indexer/imports/context.d.ts +6 -1
  217. package/dist/indexer/imports/context.d.ts.map +1 -1
  218. package/dist/indexer/imports/import-binding-tables.d.ts +3 -2
  219. package/dist/indexer/imports/import-binding-tables.d.ts.map +1 -1
  220. package/dist/indexer/imports/import-binding-tables.js +19 -22
  221. package/dist/indexer/imports/import-binding-tables.js.map +1 -1
  222. package/dist/indexer/imports/native-captures.d.ts.map +1 -1
  223. package/dist/indexer/imports/native-captures.js +10 -4
  224. package/dist/indexer/imports/native-captures.js.map +1 -1
  225. package/dist/indexer/imports/python.d.ts.map +1 -1
  226. package/dist/indexer/imports/python.js +46 -81
  227. package/dist/indexer/imports/python.js.map +1 -1
  228. package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -1
  229. package/dist/indexer/imports/text-import-extractors.js +17 -7
  230. package/dist/indexer/imports/text-import-extractors.js.map +1 -1
  231. package/dist/indexer/imports.d.ts +3 -4
  232. package/dist/indexer/imports.d.ts.map +1 -1
  233. package/dist/indexer/imports.js +106 -81
  234. package/dist/indexer/imports.js.map +1 -1
  235. package/dist/indexer/incremental-plan.d.ts.map +1 -1
  236. package/dist/indexer/incremental-plan.js +27 -11
  237. package/dist/indexer/incremental-plan.js.map +1 -1
  238. package/dist/indexer/locals-and-exports.d.ts +1 -2
  239. package/dist/indexer/locals-and-exports.d.ts.map +1 -1
  240. package/dist/indexer/locals-and-exports.js +121 -43
  241. package/dist/indexer/locals-and-exports.js.map +1 -1
  242. package/dist/indexer/member-selection.d.ts +46 -0
  243. package/dist/indexer/member-selection.d.ts.map +1 -0
  244. package/dist/indexer/member-selection.js +169 -0
  245. package/dist/indexer/member-selection.js.map +1 -0
  246. package/dist/indexer/name-lookup-policies/c-family.d.ts +1 -1
  247. package/dist/indexer/name-lookup-policies/c-family.d.ts.map +1 -1
  248. package/dist/indexer/name-lookup-policies/c-family.js +30 -10
  249. package/dist/indexer/name-lookup-policies/c-family.js.map +1 -1
  250. package/dist/indexer/name-lookup-policies/implicit-self.d.ts.map +1 -1
  251. package/dist/indexer/name-lookup-policies/implicit-self.js +14 -8
  252. package/dist/indexer/name-lookup-policies/implicit-self.js.map +1 -1
  253. package/dist/indexer/name-lookup-policies/index.d.ts.map +1 -1
  254. package/dist/indexer/name-lookup-policies/index.js +29 -3
  255. package/dist/indexer/name-lookup-policies/index.js.map +1 -1
  256. package/dist/indexer/name-lookup-policies/php.d.ts.map +1 -1
  257. package/dist/indexer/name-lookup-policies/php.js +9 -2
  258. package/dist/indexer/name-lookup-policies/php.js.map +1 -1
  259. package/dist/indexer/name-resolution-types.d.ts +2 -0
  260. package/dist/indexer/name-resolution-types.d.ts.map +1 -1
  261. package/dist/indexer/name-resolution.d.ts +5 -0
  262. package/dist/indexer/name-resolution.d.ts.map +1 -1
  263. package/dist/indexer/name-resolution.js +17 -2
  264. package/dist/indexer/name-resolution.js.map +1 -1
  265. package/dist/indexer/navigation-cpp.d.ts +8 -0
  266. package/dist/indexer/navigation-cpp.d.ts.map +1 -1
  267. package/dist/indexer/navigation-cpp.js +283 -2
  268. package/dist/indexer/navigation-cpp.js.map +1 -1
  269. package/dist/indexer/navigation-goto.d.ts +11 -2
  270. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  271. package/dist/indexer/navigation-goto.js +675 -333
  272. package/dist/indexer/navigation-goto.js.map +1 -1
  273. package/dist/indexer/navigation-local.d.ts +4 -1
  274. package/dist/indexer/navigation-local.d.ts.map +1 -1
  275. package/dist/indexer/navigation-local.js +43 -23
  276. package/dist/indexer/navigation-local.js.map +1 -1
  277. package/dist/indexer/navigation-provenance.d.ts +1 -1
  278. package/dist/indexer/navigation-provenance.d.ts.map +1 -1
  279. package/dist/indexer/navigation-provenance.js +4 -13
  280. package/dist/indexer/navigation-provenance.js.map +1 -1
  281. package/dist/indexer/navigation-references.d.ts +1 -1
  282. package/dist/indexer/navigation-references.d.ts.map +1 -1
  283. package/dist/indexer/navigation-references.js +44 -16
  284. package/dist/indexer/navigation-references.js.map +1 -1
  285. package/dist/indexer/navigation-resolve.d.ts +13 -0
  286. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  287. package/dist/indexer/navigation-resolve.js +158 -5
  288. package/dist/indexer/navigation-resolve.js.map +1 -1
  289. package/dist/indexer/navigation.d.ts +2 -1
  290. package/dist/indexer/navigation.d.ts.map +1 -1
  291. package/dist/indexer/navigation.js +82 -57
  292. package/dist/indexer/navigation.js.map +1 -1
  293. package/dist/indexer/parse-context.d.ts +2 -3
  294. package/dist/indexer/parse-context.d.ts.map +1 -1
  295. package/dist/indexer/parse-context.js +8 -21
  296. package/dist/indexer/parse-context.js.map +1 -1
  297. package/dist/indexer/reference-candidates.d.ts.map +1 -1
  298. package/dist/indexer/reference-candidates.js +13 -7
  299. package/dist/indexer/reference-candidates.js.map +1 -1
  300. package/dist/indexer/reference-context.d.ts.map +1 -1
  301. package/dist/indexer/reference-context.js +4 -1
  302. package/dist/indexer/reference-context.js.map +1 -1
  303. package/dist/indexer/scope-nodes.d.ts.map +1 -1
  304. package/dist/indexer/scope-nodes.js +5 -0
  305. package/dist/indexer/scope-nodes.js.map +1 -1
  306. package/dist/indexer/scope-types.d.ts +4 -0
  307. package/dist/indexer/scope-types.d.ts.map +1 -1
  308. package/dist/indexer/scope.d.ts +2 -3
  309. package/dist/indexer/scope.d.ts.map +1 -1
  310. package/dist/indexer/scope.js +85 -13
  311. package/dist/indexer/scope.js.map +1 -1
  312. package/dist/indexer/shared-owner-identity.js +1 -1
  313. package/dist/indexer/shared-owner-identity.js.map +1 -1
  314. package/dist/indexer/star-import-precedence.d.ts +6 -7
  315. package/dist/indexer/star-import-precedence.d.ts.map +1 -1
  316. package/dist/indexer/star-import-precedence.js +18 -12
  317. package/dist/indexer/star-import-precedence.js.map +1 -1
  318. package/dist/indexer/ts-callables.d.ts +15 -24
  319. package/dist/indexer/ts-callables.d.ts.map +1 -1
  320. package/dist/indexer/ts-callables.js +44 -75
  321. package/dist/indexer/ts-callables.js.map +1 -1
  322. package/dist/indexer/types.d.ts +23 -26
  323. package/dist/indexer/types.d.ts.map +1 -1
  324. package/dist/indexer/types.js +4 -0
  325. package/dist/indexer/types.js.map +1 -1
  326. package/dist/indexer.d.ts +2 -7
  327. package/dist/indexer.d.ts.map +1 -1
  328. package/dist/indexer.js.map +1 -1
  329. package/dist/languages/all.d.ts +1 -0
  330. package/dist/languages/all.d.ts.map +1 -1
  331. package/dist/languages/all.js +1 -0
  332. package/dist/languages/all.js.map +1 -1
  333. package/dist/languages/callable-arity.d.ts +21 -0
  334. package/dist/languages/callable-arity.d.ts.map +1 -1
  335. package/dist/languages/callable-arity.js +17 -0
  336. package/dist/languages/callable-arity.js.map +1 -1
  337. package/dist/languages/definitions/terraform.d.ts +9 -0
  338. package/dist/languages/definitions/terraform.d.ts.map +1 -0
  339. package/dist/languages/definitions/terraform.js +84 -0
  340. package/dist/languages/definitions/terraform.js.map +1 -0
  341. package/dist/languages/definitions/zig.d.ts.map +1 -1
  342. package/dist/languages/definitions/zig.js +6 -0
  343. package/dist/languages/definitions/zig.js.map +1 -1
  344. package/dist/languages.d.ts +1 -0
  345. package/dist/languages.d.ts.map +1 -1
  346. package/dist/languages.js +1 -0
  347. package/dist/languages.js.map +1 -1
  348. package/dist/lifecycle/manifest.d.ts.map +1 -1
  349. package/dist/lifecycle/manifest.js +0 -1
  350. package/dist/lifecycle/manifest.js.map +1 -1
  351. package/dist/native/byte-index.d.ts +6 -0
  352. package/dist/native/byte-index.d.ts.map +1 -1
  353. package/dist/native/byte-index.js +11 -6
  354. package/dist/native/byte-index.js.map +1 -1
  355. package/dist/native/contracts.d.ts +2 -3
  356. package/dist/native/contracts.d.ts.map +1 -1
  357. package/dist/native/execution.d.ts +9 -9
  358. package/dist/native/execution.d.ts.map +1 -1
  359. package/dist/native/execution.js +37 -77
  360. package/dist/native/execution.js.map +1 -1
  361. package/dist/native/js-bridge.d.ts +2 -15
  362. package/dist/native/js-bridge.d.ts.map +1 -1
  363. package/dist/native/js-bridge.js +2 -15
  364. package/dist/native/js-bridge.js.map +1 -1
  365. package/dist/native/query-results.js +2 -2
  366. package/dist/native/query-results.js.map +1 -1
  367. package/dist/native/runtime.d.ts +12 -12
  368. package/dist/native/runtime.d.ts.map +1 -1
  369. package/dist/native/runtime.js +24 -69
  370. package/dist/native/runtime.js.map +1 -1
  371. package/dist/native/tree-sitter-native.d.ts +3 -3
  372. package/dist/native/tree-sitter-native.d.ts.map +1 -1
  373. package/dist/native/tree-sitter-native.js +2 -2
  374. package/dist/native/tree-sitter-native.js.map +1 -1
  375. package/dist/presets.d.ts.map +1 -1
  376. package/dist/presets.js +0 -4
  377. package/dist/presets.js.map +1 -1
  378. package/dist/review.d.ts.map +1 -1
  379. package/dist/review.js +2 -20
  380. package/dist/review.js.map +1 -1
  381. package/dist/session.d.ts.map +1 -1
  382. package/dist/session.js +0 -5
  383. package/dist/session.js.map +1 -1
  384. package/dist/sql/navigation.js +1 -1
  385. package/dist/sql/navigation.js.map +1 -1
  386. package/dist/terraform/navigation.d.ts +20 -0
  387. package/dist/terraform/navigation.d.ts.map +1 -0
  388. package/dist/terraform/navigation.js +142 -0
  389. package/dist/terraform/navigation.js.map +1 -0
  390. package/dist/terraform/resolution.d.ts +82 -0
  391. package/dist/terraform/resolution.d.ts.map +1 -0
  392. package/dist/terraform/resolution.js +324 -0
  393. package/dist/terraform/resolution.js.map +1 -0
  394. package/dist/terraform/syntax.d.ts +109 -0
  395. package/dist/terraform/syntax.d.ts.map +1 -0
  396. package/dist/terraform/syntax.js +441 -0
  397. package/dist/terraform/syntax.js.map +1 -0
  398. package/dist/util/bloom-filter.d.ts +1 -0
  399. package/dist/util/bloom-filter.d.ts.map +1 -1
  400. package/dist/util/bloom-filter.js +3 -0
  401. package/dist/util/bloom-filter.js.map +1 -1
  402. package/dist/util/glob.d.ts +32 -0
  403. package/dist/util/glob.d.ts.map +1 -0
  404. package/dist/util/glob.js +137 -0
  405. package/dist/util/glob.js.map +1 -0
  406. package/dist/util/member-access-tables.d.ts.map +1 -1
  407. package/dist/util/member-access-tables.js +5 -0
  408. package/dist/util/member-access-tables.js.map +1 -1
  409. package/dist/util/member-access.d.ts.map +1 -1
  410. package/dist/util/member-access.js +5 -2
  411. package/dist/util/member-access.js.map +1 -1
  412. package/dist/util/project-files.d.ts +2 -10
  413. package/dist/util/project-files.d.ts.map +1 -1
  414. package/dist/util/project-files.js +32 -52
  415. package/dist/util/project-files.js.map +1 -1
  416. package/dist/util/python-type-checking.d.ts +18 -0
  417. package/dist/util/python-type-checking.d.ts.map +1 -0
  418. package/dist/util/python-type-checking.js +160 -0
  419. package/dist/util/python-type-checking.js.map +1 -0
  420. package/dist/util/resolution/jvm.d.ts +7 -3
  421. package/dist/util/resolution/jvm.d.ts.map +1 -1
  422. package/dist/util/resolution/jvm.js +56 -38
  423. package/dist/util/resolution/jvm.js.map +1 -1
  424. package/dist/util/resolution/rust.d.ts +0 -1
  425. package/dist/util/resolution/rust.d.ts.map +1 -1
  426. package/dist/util/resolution/rust.js +0 -9
  427. package/dist/util/resolution/rust.js.map +1 -1
  428. package/dist/util/resolution/specifier-targets.d.ts +44 -0
  429. package/dist/util/resolution/specifier-targets.d.ts.map +1 -0
  430. package/dist/util/resolution/specifier-targets.js +157 -0
  431. package/dist/util/resolution/specifier-targets.js.map +1 -0
  432. package/dist/util/resolution/terraform.d.ts +18 -0
  433. package/dist/util/resolution/terraform.d.ts.map +1 -0
  434. package/dist/util/resolution/terraform.js +64 -0
  435. package/dist/util/resolution/terraform.js.map +1 -0
  436. package/dist/util/resolution.d.ts.map +1 -1
  437. package/dist/util/resolution.js +5 -10
  438. package/dist/util/resolution.js.map +1 -1
  439. package/dist/util/specifiers.d.ts +9 -1
  440. package/dist/util/specifiers.d.ts.map +1 -1
  441. package/dist/util/specifiers.js +27 -8
  442. package/dist/util/specifiers.js.map +1 -1
  443. package/dist/util/trivia-tables.d.ts.map +1 -1
  444. package/dist/util/trivia-tables.js +9 -0
  445. package/dist/util/trivia-tables.js.map +1 -1
  446. package/dist/util/trivia.d.ts.map +1 -1
  447. package/dist/util/trivia.js +49 -30
  448. package/dist/util/trivia.js.map +1 -1
  449. package/dist/util/workspace.d.ts.map +1 -1
  450. package/dist/util/workspace.js +32 -4
  451. package/dist/util/workspace.js.map +1 -1
  452. package/package.json +6 -8
@@ -4,15 +4,14 @@ import { isPythonReceiverAttributeAssignmentName } from "../languages/definition
4
4
  import { sliceText } from "../util/ast.js";
5
5
  import { foldPhpIdentifierCase } from "../util/identifiers.js";
6
6
  import { fileIdentityKey } from "../util/paths.js";
7
- import { collectMemberAccessChain, getMemberAccessParts, getNavigationExpressionProperty, isMemberAccessNode, isReceiverNameNode, memberAccessTraversalTypes, receiverKeywordText, } from "../util/member-access.js";
8
- import { keywordReceiverKind, MEMBER_ACCESS_ROWS, supportsReceiverMemberNavigation, } from "../util/member-access-tables.js";
9
- import { cppCallableShapeForNode } from "./cpp-callables.js";
10
- import { typescriptCallableContainerKey, typescriptMergedNamespaceContainers, typescriptSelectOverloadCandidate, } from "./ts-callables.js";
7
+ import { collectMemberAccessChain, getMemberAccessParts, getNavigationExpressionProperty, isMemberAccessNode, isReceiverNameNode, memberAccessTraversalTypes, } from "../util/member-access.js";
8
+ import { MEMBER_ACCESS_ROWS, supportsReceiverMemberNavigation } from "../util/member-access-tables.js";
9
+ import { typescriptCallableContainerKey, typescriptMergedNamespaceContainers } from "./ts-callables.js";
11
10
  import { effectiveExplicitBinding, isExpandedStarBinding, resolveStarImportedName, resolveStarImportedNamespace, starImportPrecedence, } from "./star-import-precedence.js";
12
- import { classifyReceiver, cppOutOfLineOwnerPath, cppQualifiedNameSegments, declarationIsStaticEquivalent, declarationNodeIsStatic, declaresMembers, hasStaticMemberDistinction, memberContainerDef, nearestMemberContainer, keywordReceiverCrossesDynamicBoundary, isUnprovenHeritageExpression, keywordReceiverMemberScope, kotlinExtensionReceiverTypeNode, csharpDottedNameRoot, nodeInStaticMemberContext, importTypeQuerySpecifier, receiverConstructorExpression, rustImplSelfTypeNode, supportsStaticMemberScope, TRANSPARENT_MEMBER_CONTAINER_TYPES, unwrapNamedType, } from "../graphs/symbol-graph-detailed/receiver-calls.js";
13
- import { CALLABLE_DECLARATION_NODE_TYPES, getCallableArity, getCallArgumentCount, memberLookupBinding, } from "../languages/callable-arity.js";
14
- import { getCompilationUnitPeers } from "./compilation-units.js";
15
- import { isExportedDeclaration, isPrivateDeclaration, isGoExportedMemberName, isSwiftCrossFileHiddenSharedOwnerMember, } from "./declaration-visibility.js";
11
+ import { classifyReceiver, cppOutOfLineOwnerPath, cppQualifiedNameSegments, declarationIsStaticEquivalent, declarationNodeIsStatic, declaredTypeNameNode, declaresMembers, hasStaticMemberDistinction, memberContainerDef, nearestMemberContainer, isUnprovenHeritageExpression, kotlinExtensionReceiverTypeNode, csharpDottedNameRoot, nodeInStaticMemberContext, importTypeQuerySpecifier, rustImplSelfTypeNode, supportsStaticMemberScope, TRANSPARENT_MEMBER_CONTAINER_TYPES, unwrapNamedType, } from "../graphs/symbol-graph-detailed/receiver-calls.js";
12
+ import { getCallArgumentCount, memberLookupBinding } from "../languages/callable-arity.js";
13
+ import { getCompilationUnitPeers, getPackageDeclarationName } from "./compilation-units.js";
14
+ import { isExportedDeclaration, isJvmPackageSymbolVisible, isPrivateDeclaration, isGoExportedMemberName, isSwiftCrossFileHiddenSharedOwnerMember, } from "./declaration-visibility.js";
16
15
  import { ensureParsedContext } from "./parse-context.js";
17
16
  import { csharpLookupName, csharpQualifiedNameNode, findClosestScopeBinding, getOrBuildScopeIndex, resolveNamedDefinition, } from "./navigation-local.js";
18
17
  import { resolveCppQualifiedMemberContainer, cppFunctionHasImplicitThis } from "./navigation-cpp.js";
@@ -21,7 +20,81 @@ import { comparePhpReferenceNames, findPhpImportAlias } from "./navigation-php.j
21
20
  import { resolveIndexedPhpClassReference, resolvePhpNamespaceSymbol } from "./php-namespace-symbols.js";
22
21
  import { cjsRequireValueBinding, memberContainerForDefinition, resolveCsharpQualifiedName, resolveExport, resolveImported, resolvePhpExportByImportType, resolveImportTypeMember, } from "./navigation-resolve.js";
23
22
  import { CSHARP_PARTIAL_CONTAINER_TYPES, getSharedOwnerIdentity, isSwiftExtensionContainer, sharedOwnerCanUseMembers, } from "./shared-owner-identity.js";
23
+ import { hasSeparateMemberScopes, inheritsMemberOverloads, selectMember, } from "./member-selection.js";
24
24
  import { SymbolKind, } from "./types.js";
25
+ const DECLARED_FIELD_CHAIN_LANGUAGES = {
26
+ ts: true,
27
+ tsx: true,
28
+ java: true,
29
+ csharp: true,
30
+ kotlin: true,
31
+ };
32
+ /** Type-syntax nodes that wrap a declared type name together with its qualifier. */
33
+ const QUALIFIED_TYPE_NODE_TYPES = {
34
+ qualified_name: true,
35
+ scoped_type_identifier: true,
36
+ nested_type_identifier: true,
37
+ user_type: true,
38
+ generic_name: true,
39
+ generic_type: true,
40
+ };
41
+ /**
42
+ * The full spelling of a declared type, e.g. `B.Repo` for `B.Repo<T>`: the last segment alone
43
+ * would resolve to a same-named type of another namespace.
44
+ */
45
+ function qualifiedDeclaredTypeText(typeName, source) {
46
+ let top = typeName;
47
+ for (let parent = typeName.parent; parent && QUALIFIED_TYPE_NODE_TYPES[parent.type]; parent = parent.parent) {
48
+ top = parent;
49
+ }
50
+ let text = sliceText(top, source).replace(/\s+/g, "");
51
+ for (let previous = ""; previous !== text;) {
52
+ previous = text;
53
+ text = text.replace(/<[^<>]*>/g, "");
54
+ }
55
+ return text;
56
+ }
57
+ /** Type-parameter list nodes across the TypeScript, Java, C#, and Kotlin grammars. */
58
+ const TYPE_PARAMETER_LIST_TYPES = {
59
+ type_parameters: true,
60
+ type_parameter_list: true,
61
+ };
62
+ /** Names of the generic type parameters declared by `node` and its enclosing declarations. */
63
+ function typeParameterNamesInScope(node, source) {
64
+ const names = new Set();
65
+ for (let current = node; current; current = current.parent) {
66
+ for (const list of current.namedChildren) {
67
+ if (!TYPE_PARAMETER_LIST_TYPES[list.type])
68
+ continue;
69
+ for (const parameter of list.namedChildren) {
70
+ const name = parameter.childForFieldName("name") ??
71
+ parameter.namedChildren.find((child) => child.type === "identifier" || child.type === "type_identifier");
72
+ if (name)
73
+ names.add(sliceText(name, source));
74
+ }
75
+ }
76
+ }
77
+ return names;
78
+ }
79
+ export function supportsDeclaredFieldChains(languageId) {
80
+ return !!DECLARED_FIELD_CHAIN_LANGUAGES[languageId];
81
+ }
82
+ function noLexicalBinding() {
83
+ return false;
84
+ }
85
+ /** A Rust named `use crate::mod` binding names the indexed module, not a class export. */
86
+ export function resolveRustModuleNamespace(index, binding) {
87
+ if (binding.kind !== "named" || typeof binding.resolved !== "string")
88
+ return null;
89
+ const owner = index.byFile.get(fileIdentityKey(binding.resolved));
90
+ if (!owner)
91
+ return null;
92
+ const modules = owner.imports.filter((candidate) => candidate.kind === "namespace" && candidate.localNS === binding.imported);
93
+ if (modules.length !== 1)
94
+ return null;
95
+ const resolved = modules[0]?.resolved;
96
+ return typeof resolved === "string" ? resolved : null;
97
+ }
25
98
  /**
26
99
  * One bound for every receiver-hierarchy walk in this module: keyword `super`/`parent` lookup,
27
100
  * Go struct embedding, and Python base classes. Each walk keeps its own visited set, so this is a
@@ -393,6 +466,45 @@ function resolveRubyQualifiedConstantDefinition(index, mod, node, source) {
393
466
  confidence: "medium",
394
467
  });
395
468
  }
469
+ /** A fully qualified JVM package symbol, never a same-spelled type from another package. */
470
+ function resolveJvmPackageSymbol(index, packageName, symbolName, languageId, useFile) {
471
+ const samePackage = getPackageDeclarationName(index, useFile, languageId) === packageName;
472
+ let target;
473
+ for (const candidate of index.byFile.values()) {
474
+ const targetLanguage = supportForFileWithoutHeaderSample(candidate.file, index.languageExtensions)?.id;
475
+ if (targetLanguage !== "java" && targetLanguage !== "kotlin")
476
+ continue;
477
+ if (getPackageDeclarationName(index, candidate.file, targetLanguage) !== packageName)
478
+ continue;
479
+ for (const entry of candidate.exports) {
480
+ if (entry.type !== "local" ||
481
+ entry.exportedAs !== symbolName ||
482
+ entry.target.isMember ||
483
+ !isJvmPackageSymbolVisible(entry.target, targetLanguage, languageId, samePackage))
484
+ continue;
485
+ if (target &&
486
+ (target.file !== entry.target.file || target.range.start.index !== entry.target.range.start.index)) {
487
+ return undefined;
488
+ }
489
+ target = entry.target;
490
+ }
491
+ }
492
+ return target;
493
+ }
494
+ /** Package paths only bind when the leftmost name is not a lexical value or imported alias. */
495
+ function resolveJvmPackageExpression(index, sup, source, expr, resolveLexicalBinding, useFile) {
496
+ if (sup.id !== "java" && sup.id !== "kotlin")
497
+ return null;
498
+ const chain = collectMemberAccessChain({ sup, source, chainNode: expr });
499
+ if (!chain || !isReceiverNameNode(sup, chain.base.type) || resolveLexicalBinding?.(chain.base))
500
+ return null;
501
+ const parts = [sliceText(chain.base, source), ...chain.names.toReversed()];
502
+ const member = parts.pop();
503
+ if (!member || !parts.every((part) => /^[\p{L}_][\p{L}\p{N}_]*$/u.test(part)))
504
+ return null;
505
+ const target = resolveJvmPackageSymbol(index, parts.join("."), member, sup.id, useFile);
506
+ return target ? { kind: "resolved", def: target } : null;
507
+ }
396
508
  export async function resolveMemberAccessDefinition(params) {
397
509
  const { index, mod, node, source, tree, sup, resolveLexicalBinding } = params;
398
510
  if (sup.id === "ruby") {
@@ -481,6 +593,11 @@ export async function resolveMemberAccessDefinition(params) {
481
593
  if (result)
482
594
  return result;
483
595
  }
596
+ if (sup.id === "rust") {
597
+ const moduleFile = resolveRustModuleNamespace(index, imp);
598
+ if (moduleFile)
599
+ return { kind: "namespace", file: moduleFile };
600
+ }
484
601
  const result = resolveImported(index, imp, imp.kind === "named" ? imp.imported : "default");
485
602
  if (result) {
486
603
  if ("namespace" in result) {
@@ -560,6 +677,11 @@ export async function resolveMemberAccessDefinition(params) {
560
677
  }
561
678
  if (subObj && subProp) {
562
679
  const base = await resolveExpression(subObj);
680
+ if (!base) {
681
+ const qualified = resolveJvmPackageExpression(index, sup, source, expr, resolveLexicalBinding, mod.file);
682
+ if (qualified)
683
+ return qualified;
684
+ }
563
685
  const memberName = sliceText(subProp, source);
564
686
  // `P.Mix` in `P.Mix.M()`: when the leftmost name binds nothing, a C# dotted name is a
565
687
  // namespace-qualified type, which qualified export lookup resolves across every file that
@@ -574,6 +696,24 @@ export async function resolveMemberAccessDefinition(params) {
574
696
  return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
575
697
  }
576
698
  if (base?.kind === "resolved") {
699
+ if (sup.id === "go") {
700
+ const receiver = await resolveReceiverDefinition(index, subObj, source, sup, resolveExpression, mod, undefined, base);
701
+ if (receiver && declaresMembers(receiver.def)) {
702
+ const context = await ensureParsedContext(receiver.def.file, undefined, index.languageExtensions);
703
+ const embedded = goEmbeddedTypeNames(receiver.def.localName, context, context.sup.normalizeIdentifier);
704
+ if (embedded.includes(memberName)) {
705
+ const ownerModule = index.byFile.get(fileIdentityKey(receiver.def.file));
706
+ const named = ownerModule
707
+ ? resolveNamedDefinition(index, ownerModule, ownerModule.file, context.sup, memberName)
708
+ : null;
709
+ if (named?.status === "ok") {
710
+ const type = asMemberContainer(index, named.definition);
711
+ if (type)
712
+ return { kind: "resolved", def: type };
713
+ }
714
+ }
715
+ }
716
+ }
577
717
  if (sup.id === "java" || sup.id === "csharp") {
578
718
  const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName, callArgumentCountFor(expr));
579
719
  return memberDef ? { kind: "resolved", def: memberDef } : null;
@@ -595,6 +735,11 @@ export async function resolveMemberAccessDefinition(params) {
595
735
  const subProp = expr.childForFieldName("name") ?? expr.child(2);
596
736
  if (subObj && subProp) {
597
737
  const base = await resolveExpression(subObj);
738
+ if (!base) {
739
+ const qualified = resolveJvmPackageExpression(index, sup, source, expr, resolveLexicalBinding, mod.file);
740
+ if (qualified)
741
+ return qualified;
742
+ }
598
743
  const memberName = sliceText(subProp, source);
599
744
  if (base?.kind === "namespace") {
600
745
  return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
@@ -607,6 +752,22 @@ export async function resolveMemberAccessDefinition(params) {
607
752
  }
608
753
  return null;
609
754
  };
755
+ const receiverHasLexicalBinding = sup.id === "python"
756
+ ? (callee) => {
757
+ const scope = getOrBuildScopeIndex(index, mod.file, source, sup, mod, tree);
758
+ return !!findClosestScopeBinding(scope, sliceText(callee, source), callee, sup);
759
+ }
760
+ : noLexicalBinding;
761
+ const resolvedReceiver = obj && prop && node.id === prop.id ? await resolveExpression(obj) : null;
762
+ const receiverProof = obj && prop && node.id === prop.id
763
+ ? classifyReceiver(sup, obj, source, null, 0, memberNode, receiverHasLexicalBinding, () => {
764
+ if (resolvedReceiver?.kind === "namespace")
765
+ return "module-import";
766
+ if (resolvedReceiver?.kind === "resolved" && declaresMembers(resolvedReceiver.def))
767
+ return "static-type";
768
+ return null;
769
+ })
770
+ : null;
610
771
  const chain = await resolveExpression(memberNode);
611
772
  if (chain && prop && node.id === prop.id) {
612
773
  if (chain.kind === "resolved") {
@@ -628,12 +789,10 @@ export async function resolveMemberAccessDefinition(params) {
628
789
  }
629
790
  }
630
791
  }
631
- const receiverName = obj ? sliceText(obj, source) : "";
632
- const receiverKind = keywordReceiverKind(sup.id, receiverName);
633
792
  if (obj && prop && node.id === prop.id && supportsReceiverMemberNavigation(sup.id)) {
634
793
  const member = sliceText(prop, source);
635
794
  if (sup.id === "python") {
636
- const memberDef = await resolvePythonReceiverMember(index, mod, node, obj, member, source, tree, sup, resolveExpression);
795
+ const memberDef = await resolvePythonReceiverMember(index, mod, node, obj, member, source, sup, resolveExpression, receiverProof);
637
796
  if (!memberDef)
638
797
  return null;
639
798
  return okGoToResult(index, memberDef, {
@@ -642,11 +801,8 @@ export async function resolveMemberAccessDefinition(params) {
642
801
  confidence: "medium",
643
802
  });
644
803
  }
645
- if (receiverKind && keywordReceiverCrossesDynamicBoundary(sup, node)) {
646
- return null;
647
- }
648
- const keywordScope = receiverKind ? keywordReceiverMemberScope(sup, receiverName, node, source) : "any";
649
- if (receiverKind === "own") {
804
+ const keywordScope = receiverProof?.kind === "own-type" || receiverProof?.kind === "supertype" ? receiverProof.memberScope : "any";
805
+ if (receiverProof?.kind === "own-type") {
650
806
  const memberDef = await resolveKeywordReceiverMember(index, mod, node, member, keywordScope, false, getCallArgumentCount({ languageId: sup.id, source, call: memberNode.parent ?? memberNode }) ?? undefined);
651
807
  if (memberDef) {
652
808
  return okGoToResult(index, memberDef, {
@@ -673,7 +829,7 @@ export async function resolveMemberAccessDefinition(params) {
673
829
  if (sup.id === "swift")
674
830
  return { status: "not_found", reason: "No matching Swift member definition" };
675
831
  }
676
- else if (receiverKind === "supertype") {
832
+ else if (receiverProof?.kind === "supertype") {
677
833
  const memberDef = await resolveKeywordReceiverMember(index, mod, node, member, keywordScope, true, getCallArgumentCount({ languageId: sup.id, source, call: memberNode.parent ?? memberNode }) ?? undefined);
678
834
  if (!memberDef)
679
835
  return { status: "not_found", reason: "No matching supertype member definition" };
@@ -710,7 +866,7 @@ export async function resolveMemberAccessDefinition(params) {
710
866
  // function lookup resolves; the short name must not be read as a same-named class receiver.
711
867
  return null;
712
868
  }
713
- const importType = isJsTsLanguage(sup.id) ? receiverConstructorExpression(obj, source, sup) : null;
869
+ const importType = isJsTsLanguage(sup.id) && receiverProof?.kind === "named-type" ? receiverProof.typeNode : null;
714
870
  const importSpecifier = importType?.type === "type_query" ? importTypeQuerySpecifier(importType) : null;
715
871
  if (importSpecifier) {
716
872
  const memberDef = resolveImportTypeMember(index, mod.file, importSpecifier, member);
@@ -722,7 +878,7 @@ export async function resolveMemberAccessDefinition(params) {
722
878
  })
723
879
  : null;
724
880
  }
725
- const receiver = await resolveReceiverDefinition(index, obj, source, sup, resolveExpression, mod);
881
+ const receiver = await resolveReceiverDefinition(index, obj, source, sup, resolveExpression, mod, receiverProof, resolvedReceiver);
726
882
  if (receiver) {
727
883
  const objDef = receiver.def;
728
884
  const targetContext = await ensureParsedContext(objDef.file, undefined, index.languageExtensions);
@@ -749,22 +905,48 @@ export async function resolveMemberAccessDefinition(params) {
749
905
  : (local) => matchesReceiverMemberScope(local, receiver.memberScope, targetContext, container);
750
906
  const knownArgumentCount = getCallArgumentCount({ languageId: sup.id, source, call: memberNode.parent ?? memberNode }) ?? undefined;
751
907
  let memberDef;
752
- if ((targetContext.sup.id === "ts" || targetContext.sup.id === "tsx") &&
908
+ const hierarchyLanguage = isJsTsLanguage(targetContext.sup.id) ||
909
+ targetContext.sup.id === "ruby" ||
910
+ targetContext.sup.id === "cpp" ||
911
+ targetContext.sup.id === "csharp" ||
912
+ targetContext.sup.id === "java" ||
913
+ targetContext.sup.id === "kotlin" ||
914
+ targetContext.sup.id === "php" ||
915
+ targetContext.sup.id === "swift";
916
+ if (hierarchyLanguage && declaresMembers(objDef) && !receiver.runtimeTypeOnly) {
917
+ const report = { named: false, ambiguous: false };
918
+ memberDef = await resolveKeywordReceiverMember(index, mod, node, member, receiver.memberScope, false, knownArgumentCount, objDef, report);
919
+ if (!memberDef && report.named)
920
+ return { status: "not_found", reason: "No unique receiver member" };
921
+ }
922
+ if (!memberDef &&
923
+ (targetContext.sup.id === "ts" || targetContext.sup.id === "tsx") &&
753
924
  (container.type === "internal_module" || container.type === "module")) {
754
925
  memberDef = await findReceiverMemberDefinition(index, targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier, receiver.memberScope, knownArgumentCount);
755
926
  }
756
- else if (receiver.runtimeTypeOnly || targetContext.sup.id === "java") {
927
+ else if (!memberDef && (receiver.runtimeTypeOnly || targetContext.sup.id === "java")) {
757
928
  const candidates = findDirectLocalsWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier, memberPredicate);
758
- memberDef = await selectReceiverMemberCandidates(index, candidates, knownArgumentCount);
929
+ const selected = selectMember([objDef], indexedMemberModel(index, candidates, targetContext.sup.id), {
930
+ name: member,
931
+ argumentCount: knownArgumentCount ?? null,
932
+ scope: "any",
933
+ useFile: mod.file,
934
+ phpCaseInsensitive: targetContext.sup.id === "php",
935
+ keepUniqueArityMismatch: true,
936
+ });
937
+ memberDef = selected.status === "unique" ? selected.member : undefined;
759
938
  }
760
- else {
939
+ else if (!memberDef) {
761
940
  memberDef = await findReceiverMemberDefinition(index, targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier, receiver.memberScope, knownArgumentCount);
762
941
  }
942
+ const memberContext = memberDef && fileIdentityKey(memberDef.file) !== fileIdentityKey(objDef.file)
943
+ ? await ensureParsedContext(memberDef.file, undefined, index.languageExtensions)
944
+ : targetContext;
763
945
  if (memberDef &&
764
946
  (sup.id === "cpp" ||
765
947
  isGoExportedMemberName(sup.id, member) ||
766
948
  getCompilationUnitPeers(index, mod.file).files.has(memberDef.file)) &&
767
- !crossFilePeerMemberHidden(mod.file, memberDef, targetContext)) {
949
+ !crossFilePeerMemberHidden(mod.file, memberDef, memberContext)) {
768
950
  return okGoToResult(index, memberDef, {
769
951
  via: { exportedName: member },
770
952
  resolution: "member-access",
@@ -1135,7 +1317,7 @@ export async function provenClassifiedReceiverOmitsMember(index, fileId, parsed,
1135
1317
  const scope = getOrBuildScopeIndex(index, fileId, parsed.source, parsed.sup, mod, parsed.tree);
1136
1318
  return !!findClosestScopeBinding(scope, sliceText(callee, parsed.source), callee, parsed.sup);
1137
1319
  });
1138
- if (!receiver)
1320
+ if (receiver.kind === "unknown" || receiver.kind === "module-import")
1139
1321
  return false;
1140
1322
  if (receiver.kind === "named-type") {
1141
1323
  const def = await resolveReceiverTypeName(index, mod, parsed.sup, receiver.typeName);
@@ -1219,6 +1401,11 @@ async function baseRefsFromContainer(index, mod, container, source, sup, supercl
1219
1401
  let def = base.kind === "simple"
1220
1402
  ? resolveNamedMemberContainer(index, mod, base.name, normalize)
1221
1403
  : await resolveQualifiedMemberContainer(index, mod, base.base, base.path, normalize, sup);
1404
+ if (!def && base.kind === "simple" && sup.id !== "php") {
1405
+ const named = resolveNamedDefinition(index, mod, mod.file, sup, base.name, undefined, container.startIndex);
1406
+ if (named?.status === "ok")
1407
+ def = asMemberContainer(index, named.definition);
1408
+ }
1222
1409
  if (!def && sup.id === "php" && base.kind === "simple") {
1223
1410
  def = resolvePhpNamespaceSymbol(index, source, tree, container, base.name, mod.imports, "class") ?? undefined;
1224
1411
  }
@@ -1249,152 +1436,135 @@ async function baseRefsFromContainer(index, mod, container, source, sup, supercl
1249
1436
  }
1250
1437
  return refs;
1251
1438
  }
1252
- const HIERARCHY_OVERLOAD_LANGUAGES = new Set(["java", "kotlin", "csharp"]);
1253
1439
  async function resolveKeywordReceiverMember(index, mod, node, member, memberScope, startAtAncestor, knownArgumentCount, explicitClassDef, report) {
1254
1440
  const current = explicitClassDef
1255
1441
  ? await keywordClassRefFromDef(index, explicitClassDef)
1256
1442
  : await keywordClassRefFromNode(index, mod, node);
1257
1443
  if (!current)
1258
1444
  return undefined;
1259
- let level = startAtAncestor
1260
- ? await baseRefsFromContainer(index, current.module, current.container, current.context.source, current.context.sup, true, current.context.tree)
1261
- : [current];
1262
- if (level.length === 0)
1263
- return undefined;
1264
- // Java, Kotlin, and C# overload across the hierarchy: when no member at one level accepts the
1265
- // call, a base level may. C++ and Swift hide a base name behind any same-named member.
1266
- // An unknown count (a Kotlin spread) keeps every non-overridden overload as a candidate.
1267
- const spansHierarchy = HIERARCHY_OVERLOAD_LANGUAGES.has(current.context.sup.id);
1268
- // Java, Kotlin, and C# base members that are private are not accessible from a subclass.
1269
- const filtersPrivateBases = HIERARCHY_OVERLOAD_LANGUAGES.has(current.context.sup.id);
1270
- let lenient;
1271
- // Accepted overloads across levels. A deeper one is overridden only by an accepted method with
1272
- // the same parameter types in a class proven to derive from its owner on the walked path;
1273
- // unrelated owners with one signature (two interfaces) stay separate and ambiguous.
1274
- const accepted = [];
1445
+ const spansHierarchy = inheritsMemberOverloads(current.context.sup.id);
1446
+ const ownerKey = (ref) => keywordContainerKey(ref.file, ref.container);
1447
+ const preloadHiddenNames = isJsTsLanguage(current.context.sup.id) && knownArgumentCount !== undefined;
1275
1448
  const memberKey = (def) => `${fileIdentityKey(def.file)}:${def.range.start.index}`;
1276
- const ownerOf = new Map();
1277
- const subclassesOf = new Map();
1278
- const recordOwner = (from, owner) => {
1279
- for (let at = from; at < matches.length; at += 1)
1280
- ownerOf.set(memberKey(matches[at]), owner);
1281
- };
1282
- let matches = [];
1283
- const visited = new Set([
1284
- keywordContainerKey(current.file, current.container),
1285
- ...level.map((candidate) => keywordContainerKey(candidate.file, candidate.container)),
1286
- ]);
1449
+ const parentsByKey = new Map();
1450
+ const membersByKey = new Map();
1451
+ const scopeByMember = new Map();
1452
+ const visible = new Set();
1453
+ let level = [current];
1454
+ const seen = new Set([ownerKey(current)]);
1287
1455
  for (let depth = 0; depth < RECEIVER_HIERARCHY_DEPTH && level.length; depth += 1) {
1288
- matches = [];
1289
- for (const candidate of level) {
1290
- const ownerKey = keywordContainerKey(candidate.file, candidate.container);
1291
- const before = matches.length;
1292
- const memberPredicate = memberScope === "any"
1293
- ? undefined
1294
- : (local) => matchesReceiverMemberScope(local, memberScope, candidate.context, candidate.container);
1295
- appendDirectKeywordMembers(candidate.module.locals, member, candidate.container, candidate.context, candidate.context.sup.normalizeIdentifier, memberPredicate, matches);
1296
- recordOwner(before, ownerKey);
1297
- }
1298
- for (const candidate of level) {
1299
- if (candidate.context.sup.id !== "csharp" && candidate.context.sup.id !== "swift")
1300
- continue;
1301
- const ownerKey = keywordContainerKey(candidate.file, candidate.container);
1302
- const before = matches.length;
1303
- const sharedContainers = await resolveSharedOwnerContainers({
1304
- index,
1305
- ownerFile: candidate.file,
1306
- ownerContainer: candidate.container,
1307
- ownerSource: candidate.context.source,
1308
- languageId: candidate.context.sup.id,
1309
- });
1310
- for (const shared of sharedContainers) {
1311
- const crossFileSwift = candidate.context.sup.id === "swift" && fileIdentityKey(candidate.file) !== fileIdentityKey(shared.file);
1312
- const sharedPredicate = (local) => {
1313
- if (memberScope !== "any" &&
1314
- !matchesReceiverMemberScope(local, memberScope, shared.context, shared.container)) {
1315
- return false;
1456
+ const next = [];
1457
+ let nameFound = false;
1458
+ for (const ref of level) {
1459
+ const key = ownerKey(ref);
1460
+ const matches = [];
1461
+ if (!startAtAncestor || depth) {
1462
+ appendDirectKeywordMembers(ref.module.locals, member, ref.container, ref.context, ref.context.sup.normalizeIdentifier, undefined, matches);
1463
+ if (isJsTsLanguage(ref.context.sup.id) && ref.container.type === "interface_declaration") {
1464
+ const owner = memberContainerDef(ref.module, ref.container);
1465
+ if (owner) {
1466
+ for (const hit of typescriptMergedInterfaceMemberCandidates(ref.module.locals, member, owner, ref.container, ref.context, ref.context.sup.normalizeIdentifier, undefined)) {
1467
+ if (!matches.includes(hit))
1468
+ matches.push(hit);
1469
+ }
1316
1470
  }
1317
- if (!crossFileSwift)
1318
- return true;
1319
- const nameNode = nameNodeForDef(shared.context, local);
1320
- return !!nameNode && !isSwiftCrossFileHiddenSharedOwnerMember("swift", candidate.file, shared.file, nameNode);
1321
- };
1322
- appendDirectKeywordMembers(shared.module.locals, member, shared.container, shared.context, shared.context.sup.normalizeIdentifier, sharedPredicate, matches);
1323
- }
1324
- // Partial parts of one type share its identity.
1325
- recordOwner(before, ownerKey);
1326
- }
1327
- let uniqueMatches = uniqueReceiverMemberCandidates(matches);
1328
- // A private member of a base class is not accessible: it neither answers nor stops the walk.
1329
- // The first level of a `this` lookup is the class itself, including C# partial parts.
1330
- if (filtersPrivateBases && (startAtAncestor || depth > 0) && uniqueMatches.length) {
1331
- const inherited = [];
1332
- for (const candidate of uniqueMatches) {
1333
- if (!(await isUninheritedPrivateMember(index, mod, node, candidate)))
1334
- inherited.push(candidate);
1335
- }
1336
- uniqueMatches = inherited;
1337
- }
1338
- if (uniqueMatches.length && report)
1339
- report.named = true;
1340
- if (uniqueMatches.length) {
1341
- const allowUniqueArityMismatch = !startAtAncestor && depth === 0;
1342
- if (!spansHierarchy) {
1343
- return await selectReceiverMemberCandidates(index, uniqueMatches, knownArgumentCount, allowUniqueArityMismatch);
1344
- }
1345
- for (const candidate of uniqueMatches) {
1346
- if (knownArgumentCount !== undefined &&
1347
- (await receiverMemberAcceptsArgumentCount(index, candidate, knownArgumentCount)) === false) {
1348
- continue;
1349
1471
  }
1350
- const owner = ownerOf.get(memberKey(candidate)) ?? "";
1351
- const subclasses = subclassesOf.get(owner);
1352
- let overridden = false;
1353
- for (const entry of accepted) {
1354
- if (subclasses?.has(entry.owner) && (await sameParameterTypes(index, entry.def, candidate))) {
1355
- overridden = true;
1356
- break;
1472
+ if (ref.context.sup.id === "csharp" || ref.context.sup.id === "swift") {
1473
+ const shared = await resolveSharedOwnerContainers({
1474
+ index,
1475
+ ownerFile: ref.file,
1476
+ ownerContainer: ref.container,
1477
+ ownerSource: ref.context.source,
1478
+ languageId: ref.context.sup.id,
1479
+ });
1480
+ for (const peer of shared) {
1481
+ const peerMatches = [];
1482
+ appendDirectKeywordMembers(peer.module.locals, member, peer.container, peer.context, peer.context.sup.normalizeIdentifier, undefined, peerMatches);
1483
+ for (const hit of peerMatches) {
1484
+ if (peer.context.sup.id === "swift" && crossFilePeerMemberHidden(mod.file, hit, peer.context))
1485
+ continue;
1486
+ matches.push(hit);
1487
+ scopeByMember.set(hit, hasStaticModifier(hit, peer.context, peer.container) ? "static" : "instance");
1488
+ }
1357
1489
  }
1358
1490
  }
1359
- if (!overridden)
1360
- accepted.push({ def: candidate, owner });
1361
1491
  }
1362
- // Navigation still names the only incompatible candidate when no ancestor accepts the call.
1363
- if (allowUniqueArityMismatch && !lenient) {
1364
- lenient = await selectReceiverMemberCandidates(index, uniqueMatches, knownArgumentCount, true);
1492
+ membersByKey.set(key, matches);
1493
+ for (const hit of matches) {
1494
+ if (!scopeByMember.has(hit)) {
1495
+ scopeByMember.set(hit, hasStaticModifier(hit, ref.context, ref.container) ? "static" : "instance");
1496
+ }
1497
+ if (spansHierarchy && (startAtAncestor || depth) && (await isUninheritedPrivateMember(index, mod, node, hit))) {
1498
+ continue;
1499
+ }
1500
+ visible.add(hit);
1501
+ nameFound = true;
1365
1502
  }
1366
- }
1367
- const next = [];
1368
- for (const candidate of level) {
1369
- const childKey = keywordContainerKey(candidate.file, candidate.container);
1370
- const childSubclasses = subclassesOf.get(childKey);
1371
- for (const parent of await baseRefsFromContainer(index, candidate.module, candidate.container, candidate.context.source, candidate.context.sup, startAtAncestor, candidate.context.tree)) {
1372
- const key = keywordContainerKey(parent.file, parent.container);
1373
- // Every class on a path to this ancestor derives from it, including through a diamond.
1374
- const subclasses = subclassesOf.get(key) ?? new Set();
1375
- subclasses.add(childKey);
1376
- for (const subclass of childSubclasses ?? [])
1377
- subclasses.add(subclass);
1378
- subclassesOf.set(key, subclasses);
1379
- if (visited.has(key))
1503
+ if (nameFound && !spansHierarchy && !preloadHiddenNames)
1504
+ continue;
1505
+ const bases = await baseRefsFromContainer(index, ref.module, ref.container, ref.context.source, ref.context.sup, startAtAncestor, ref.context.tree);
1506
+ parentsByKey.set(key, bases);
1507
+ for (const base of bases) {
1508
+ const baseKey = ownerKey(base);
1509
+ if (seen.has(baseKey))
1380
1510
  continue;
1381
- visited.add(key);
1382
- next.push(parent);
1511
+ seen.add(baseKey);
1512
+ next.push(base);
1383
1513
  }
1384
1514
  }
1515
+ if (nameFound && !spansHierarchy && !preloadHiddenNames)
1516
+ break;
1385
1517
  level = next;
1386
1518
  }
1387
- if (!spansHierarchy)
1388
- return undefined;
1389
- // Without type ranking, two surviving overloads are ambiguous, including a fixed-arity and a
1390
- // variable-arity one: `hit(String)` and `hit(int...)` both take one argument, and only argument
1391
- // types decide.
1392
- if (accepted.length > 1) {
1393
- if (report)
1394
- report.ambiguous = true;
1395
- return undefined;
1519
+ const sameSignatures = new Map();
1520
+ if (spansHierarchy) {
1521
+ const all = [...membersByKey.values()].flat().filter((candidate) => visible.has(candidate));
1522
+ for (let left = 0; left < all.length; left += 1) {
1523
+ for (let right = left + 1; right < all.length; right += 1) {
1524
+ const a = all[left];
1525
+ const b = all[right];
1526
+ if (!(await sameParameterTypes(index, a, b)))
1527
+ continue;
1528
+ const aKey = memberKey(a);
1529
+ const bKey = memberKey(b);
1530
+ const identical = sameSignatures.get(aKey) ?? new Set();
1531
+ identical.add(bKey);
1532
+ sameSignatures.set(aKey, identical);
1533
+ }
1534
+ }
1535
+ }
1536
+ const model = {
1537
+ ownerKey,
1538
+ members: (ref) => membersByKey.get(ownerKey(ref)) ?? [],
1539
+ supertypes: (ref) => parentsByKey.get(ownerKey(ref)) ?? [],
1540
+ name: (def) => def.localName,
1541
+ key: (def) => def.callable?.key ?? memberKey(def),
1542
+ callable: (def) => {
1543
+ const facts = def.callable;
1544
+ if (!facts || memberLookupBinding(current.context.sup.id) !== "unbound")
1545
+ return facts;
1546
+ return facts.unboundArity ? { ...facts, arity: facts.unboundArity } : facts;
1547
+ },
1548
+ scope: (def) => scopeByMember.get(def) ?? "any",
1549
+ visible: (def) => visible.has(def),
1550
+ sameSignature: (a, b) => sameSignatures.get(memberKey(a))?.has(memberKey(b)) ?? false,
1551
+ };
1552
+ const selected = selectMember([current], model, {
1553
+ name: member,
1554
+ argumentCount: knownArgumentCount ?? null,
1555
+ scope: memberScope,
1556
+ useFile: mod.file,
1557
+ startAtAncestor,
1558
+ keepUniqueArityMismatch: !startAtAncestor,
1559
+ inheritOverloads: spansHierarchy,
1560
+ phpCaseInsensitive: current.context.sup.id === "php",
1561
+ separateMemberScopes: hasSeparateMemberScopes(current.context.sup.id),
1562
+ });
1563
+ if (report) {
1564
+ report.named = selected.named;
1565
+ report.ambiguous = selected.status === "ambiguous";
1396
1566
  }
1397
- return accepted[0]?.def ?? lenient;
1567
+ return selected.status === "unique" ? selected.member : undefined;
1398
1568
  }
1399
1569
  /** The parameter list of a Java, Kotlin, or C# method declaration. */
1400
1570
  async function memberParameterList(index, def) {
@@ -1500,7 +1670,7 @@ const BUILTIN_PARAMETER_TYPES = {
1500
1670
  * other. Equal spelling is proof only within one file or for built-in types; elsewhere each
1501
1671
  * spelling must resolve to the same declaration from its own file.
1502
1672
  */
1503
- async function sameParameterTypes(index, left, right) {
1673
+ export async function sameParameterTypes(index, left, right) {
1504
1674
  // A type parameter (`T`) names a different type in each declaration after substitution, so
1505
1675
  // equal spelling proves nothing.
1506
1676
  const [leftGenerics, rightGenerics] = await Promise.all([
@@ -1601,7 +1771,7 @@ export async function resolveImplicitSelfMember(index, mod, node, name, source,
1601
1771
  // Any inherited instance method of that name hides the import, even when none applies.
1602
1772
  return instance || instanceReport.named ? null : undefined;
1603
1773
  }
1604
- /** Whether a Java or Kotlin member is `private` and declared outside the class enclosing the use. */
1774
+ /** Whether an inherited JVM member is inaccessible through this receiver. */
1605
1775
  async function isUninheritedPrivateMember(index, mod, use, member) {
1606
1776
  const container = findEnclosingClassContainer(use);
1607
1777
  const start = member.range.start.index ?? -1;
@@ -1611,6 +1781,13 @@ async function isUninheritedPrivateMember(index, mod, use, member) {
1611
1781
  start < container.endIndex;
1612
1782
  if (ownMember)
1613
1783
  return false;
1784
+ if (member.javaPackagePrivate && !member.javaProtectedMember) {
1785
+ const memberPackage = getPackageDeclarationName(index, member.file, "java");
1786
+ const useLanguage = supportForFileWithoutHeaderSample(mod.file, index.languageExtensions)?.id;
1787
+ const usePackage = getPackageDeclarationName(index, mod.file, useLanguage === "kotlin" ? "kotlin" : "java");
1788
+ if (memberPackage !== usePackage)
1789
+ return true;
1790
+ }
1614
1791
  const parsed = await ensureParsedContext(member.file, index.parsed?.get(fileIdentityKey(member.file)), index.languageExtensions).catch(() => null);
1615
1792
  const nameNode = parsed?.tree.rootNode.descendantForIndex(start, member.range.end.index ?? start);
1616
1793
  return !!parsed && !!nameNode && isPrivateDeclaration(parsed.sup.id, nameNode);
@@ -1690,7 +1867,7 @@ export async function resolveCppOutOfLineImplicitMember(index, mod, node, name,
1690
1867
  // the name but is not the call's target, so no consumer may fall back to a same-named free function.
1691
1868
  const rejected = requireAcceptedArity &&
1692
1869
  argumentCount !== undefined &&
1693
- !(await receiverMemberAcceptsArgumentCount(index, member, argumentCount));
1870
+ !receiverMemberAcceptsArgumentCount(index, member, argumentCount);
1694
1871
  return rejected ? null : member;
1695
1872
  }
1696
1873
  export { supportsReceiverCallEdges, supportsReceiverMemberNavigation } from "../util/member-access-tables.js";
@@ -1756,8 +1933,90 @@ export async function resolveRubySuperDefinition(index, mod, node, source, sup)
1756
1933
  return undefined;
1757
1934
  return resolveKeywordReceiverMember(index, mod, node, member, "any", true);
1758
1935
  }
1759
- async function resolveReceiverDefinition(index, obj, source, sup, resolveExpression, mod) {
1760
- const constructor = receiverConstructorExpression(obj, source, sup);
1936
+ /** Follow a Swift typealias only when its right-hand side is a single indexed nominal type. */
1937
+ async function resolveSwiftAliasContainer(index, alias) {
1938
+ let current = alias;
1939
+ const seen = new Set();
1940
+ while (current.kind === SymbolKind.TypeAlias) {
1941
+ const key = `${fileIdentityKey(current.file)}:${current.range.start.index}`;
1942
+ if (seen.has(key))
1943
+ return undefined;
1944
+ seen.add(key);
1945
+ const mod = index.byFile.get(fileIdentityKey(current.file));
1946
+ if (!mod)
1947
+ return undefined;
1948
+ const context = await ensureParsedContext(current.file, index.parsed?.get(fileIdentityKey(current.file)), index.languageExtensions);
1949
+ if (context.sup.id !== "swift")
1950
+ return undefined;
1951
+ const declaration = nameNodeForDef(context, current)?.parent;
1952
+ if (declaration?.type !== "typealias_declaration") {
1953
+ return declaration?.type === "class_declaration" && declaresMembers(current) ? current : undefined;
1954
+ }
1955
+ const target = declaration.namedChildren.find((child) => child.type === "user_type");
1956
+ const named = target ? unwrapNamedType(target, context.sup) : null;
1957
+ if (!named || target?.namedChildren.length !== 1)
1958
+ return undefined;
1959
+ const targetName = sliceText(named, context.source);
1960
+ const namedTarget = resolveNamedDefinition(index, mod, mod.file, context.sup, targetName, undefined, declaration.startIndex);
1961
+ const next = resolveNamedMemberContainer(index, mod, targetName, context.sup.normalizeIdentifier) ??
1962
+ (namedTarget?.status === "ok" ? asMemberContainer(index, namedTarget.definition) : undefined);
1963
+ if (!next)
1964
+ return undefined;
1965
+ current = next;
1966
+ }
1967
+ return declaresMembers(current) ? current : undefined;
1968
+ }
1969
+ async function resolveReceiverDefinition(index, obj, source, sup, resolveExpression, mod, proof, resolvedDirect) {
1970
+ const direct = resolvedDirect === undefined ? await resolveExpression(obj) : resolvedDirect;
1971
+ const receiver = proof ??
1972
+ classifyReceiver(sup, obj, source, null, 0, obj.parent ?? obj, noLexicalBinding, () => {
1973
+ if (direct?.kind === "namespace")
1974
+ return "module-import";
1975
+ if (direct?.kind === "resolved" && declaresMembers(direct.def))
1976
+ return "static-type";
1977
+ return null;
1978
+ });
1979
+ if (receiver.kind === "module-import")
1980
+ return null;
1981
+ if (supportsDeclaredFieldChains(sup.id) && isMemberAccessNode(sup, obj)) {
1982
+ const directType = direct?.kind === "resolved" ? asMemberContainer(index, direct.def) : undefined;
1983
+ if (!directType) {
1984
+ const { object, property } = getMemberAccessParts(sup, obj);
1985
+ if (!object || !property)
1986
+ return null;
1987
+ const owner = await resolveReceiverDefinition(index, object, source, sup, resolveExpression, mod);
1988
+ if (!owner || owner.runtimeTypeOnly)
1989
+ return null;
1990
+ const field = await resolveKeywordReceiverMember(index, mod, property, sliceText(property, source), owner.memberScope, false, undefined, owner.def);
1991
+ if (!field || field.kind !== SymbolKind.Variable || !field.isMember)
1992
+ return null;
1993
+ const fieldContext = await ensureParsedContext(field.file, undefined, index.languageExtensions);
1994
+ const name = nameNodeForDef(fieldContext, field);
1995
+ let declaration = name?.parent ?? null;
1996
+ if (declaration?.type === "variable_declarator")
1997
+ declaration = declaration.parent;
1998
+ if (!declaration)
1999
+ return null;
2000
+ const annotatedType = declaredTypeNameNode(declaration, fieldContext.sup);
2001
+ if (!annotatedType)
2002
+ return null;
2003
+ const fieldModule = index.byFile.get(fileIdentityKey(field.file));
2004
+ if (!fieldModule)
2005
+ return null;
2006
+ const typeText = qualifiedDeclaredTypeText(annotatedType, fieldContext.source);
2007
+ // A type parameter in scope (`class Host<Repo>`) is not a nominal type; bounds are not solved.
2008
+ if (typeParameterNamesInScope(declaration, fieldContext.source).has(typeText.split(/[.:]/)[0]))
2009
+ return null;
2010
+ const type = await resolveReceiverTypeName(index, fieldModule, fieldContext.sup, typeText);
2011
+ return type ? { def: type, memberScope: "instance" } : null;
2012
+ }
2013
+ }
2014
+ if (receiver.kind === "own-type") {
2015
+ const container = nearestMemberContainer(obj);
2016
+ const owner = container ? definitionForContainer(mod, container) : undefined;
2017
+ return owner ? { def: owner, memberScope: receiver.memberScope } : null;
2018
+ }
2019
+ const constructor = receiver.kind === "named-type" && receiver.proof !== "static-type" ? receiver.typeNode : null;
1761
2020
  if (constructor) {
1762
2021
  if (sup.id === "cpp") {
1763
2022
  const qualifiedType = cppQualifiedNameSegments(constructor, source);
@@ -1779,6 +2038,12 @@ async function resolveReceiverDefinition(index, obj, source, sup, resolveExpress
1779
2038
  memberScope: hasStaticMemberDistinction(sup.id) ? "instance" : "any",
1780
2039
  };
1781
2040
  }
2041
+ if (sup.id === "go") {
2042
+ const named = resolveNamedDefinition(index, mod, mod.file, sup, typeName, undefined, constructor.startIndex);
2043
+ const peer = named?.status === "ok" ? asMemberContainer(index, named.definition) : undefined;
2044
+ if (peer)
2045
+ return { def: peer, memberScope: "any" };
2046
+ }
1782
2047
  if (sup.id === "php") {
1783
2048
  const normalizeTypeName = (name) => foldPhpIdentifierCase(sup.normalizeIdentifier(name));
1784
2049
  const namedContainer = resolveNamedMemberContainer(index, mod, typeName, normalizeTypeName);
@@ -1816,7 +2081,12 @@ async function resolveReceiverDefinition(index, obj, source, sup, resolveExpress
1816
2081
  };
1817
2082
  }
1818
2083
  }
1819
- const direct = await resolveExpression(obj);
2084
+ if (sup.id === "swift" && direct?.kind === "resolved" && direct.def.kind === SymbolKind.TypeAlias) {
2085
+ const aliased = await resolveSwiftAliasContainer(index, direct.def);
2086
+ if (aliased)
2087
+ return { def: aliased, memberScope: "static" };
2088
+ return null;
2089
+ }
1820
2090
  const directContainer = direct?.kind === "resolved" ? asMemberContainer(index, direct.def) : undefined;
1821
2091
  if (directContainer) {
1822
2092
  if (isJsTsLanguage(sup.id) && directContainer.kind === SymbolKind.TypeAlias) {
@@ -1882,16 +2152,26 @@ async function resolveMemberDefinitionForBase(index, baseDef, member, knownArgum
1882
2152
  candidates.push(hit);
1883
2153
  }
1884
2154
  }
1885
- if (candidates.length > 1 && languageId !== "ruby") {
1886
- const reachable = [];
1887
- for (const candidate of candidates) {
1888
- if (!declaresMembers(baseDef) || (await reachableThroughTypeName(index, candidate)))
1889
- reachable.push(candidate);
2155
+ if (candidates.length) {
2156
+ let reachable = candidates;
2157
+ if (languageId !== "ruby" && candidates.length > 1) {
2158
+ reachable = [];
2159
+ for (const candidate of candidates) {
2160
+ if (!declaresMembers(baseDef) || (await reachableThroughTypeName(index, candidate)))
2161
+ reachable.push(candidate);
2162
+ }
1890
2163
  }
1891
- return await selectReceiverMemberCandidates(index, reachable, knownArgumentCount);
2164
+ const selected = selectMember([baseDef], indexedMemberModel(index, reachable, languageId), {
2165
+ name: member,
2166
+ argumentCount: knownArgumentCount ?? null,
2167
+ scope: "any",
2168
+ useFile: baseDef.file,
2169
+ phpCaseInsensitive: languageId === "php",
2170
+ firstDeclarationWins: languageId === "ruby",
2171
+ keepUniqueArityMismatch: true,
2172
+ });
2173
+ return selected.status === "unique" ? selected.member : undefined;
1892
2174
  }
1893
- if (candidates[0])
1894
- return candidates[0];
1895
2175
  if (languageId === "java")
1896
2176
  return undefined;
1897
2177
  return await findReceiverMemberDefinition(index, targetModule.locals, member, baseDef, container, targetContext, normalizeIdentifier);
@@ -1956,7 +2236,14 @@ async function findReceiverMemberDefinition(index, locals, member, receiverDef,
1956
2236
  if ((targetContext.sup.id === "ts" || targetContext.sup.id === "tsx") &&
1957
2237
  (container.type === "internal_module" || container.type === "module")) {
1958
2238
  const candidates = findTypeScriptNamespaceMemberCandidates(locals, member, receiverDef, targetContext);
1959
- return await selectReceiverMemberCandidates(index, candidates, knownArgumentCount);
2239
+ const selected = selectMember([receiverDef], indexedMemberModel(index, candidates, targetContext.sup.id), {
2240
+ name: member,
2241
+ argumentCount: knownArgumentCount ?? null,
2242
+ scope: "any",
2243
+ useFile: receiverDef.file,
2244
+ keepUniqueArityMismatch: true,
2245
+ });
2246
+ return selected.status === "unique" ? selected.member : undefined;
1960
2247
  }
1961
2248
  const allReceiverMatches = typescriptMergedInterfaceMemberCandidates(locals, member, receiverDef, container, targetContext, normalizeIdentifier, memberPredicate);
1962
2249
  if (targetContext.sup.id === "csharp" || targetContext.sup.id === "swift") {
@@ -1975,22 +2262,33 @@ async function findReceiverMemberDefinition(index, locals, member, receiverDef,
1975
2262
  }
1976
2263
  }
1977
2264
  if (allReceiverMatches.length) {
1978
- return await selectReceiverMemberCandidates(index, allReceiverMatches, knownArgumentCount);
2265
+ const selected = selectMember([receiverDef], indexedMemberModel(index, allReceiverMatches, targetContext.sup.id), {
2266
+ name: member,
2267
+ argumentCount: knownArgumentCount ?? null,
2268
+ scope: "any",
2269
+ useFile: receiverDef.file,
2270
+ phpCaseInsensitive: targetContext.sup.id === "php",
2271
+ keepUniqueArityMismatch: true,
2272
+ });
2273
+ return selected.status === "unique" ? selected.member : undefined;
1979
2274
  }
1980
2275
  if (targetContext.sup.id === "rust") {
1981
- const matches = [];
1982
- for (const implNode of findRustImplsForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source, targetContext.sup)) {
1983
- appendDirectKeywordMembers(locals, member, implNode, targetContext, normalizeIdentifier, undefined, matches);
1984
- }
1985
- return await selectReceiverMemberCandidates(index, matches, knownArgumentCount);
2276
+ return selectRustReceiverMember(index, receiverDef, member, targetContext, locals, knownArgumentCount);
1986
2277
  }
1987
2278
  if (targetContext.sup.id === "go") {
1988
- return findGoReceiverMember(locals, member, receiverDef.localName, targetContext, normalizeIdentifier);
2279
+ return selectGoReceiverMember(index, receiverDef, member, targetContext.sup.normalizeIdentifier, knownArgumentCount);
1989
2280
  }
1990
2281
  if (targetContext.sup.id === "kotlin") {
1991
2282
  const extensionMatches = kotlinExtensionFunctionsNamedOnType(locals, member, receiverDef.localName, targetContext, normalizeIdentifier);
1992
2283
  if (extensionMatches.length) {
1993
- return await selectReceiverMemberCandidates(index, extensionMatches, knownArgumentCount);
2284
+ const selected = selectMember([receiverDef], indexedMemberModel(index, extensionMatches, targetContext.sup.id), {
2285
+ name: member,
2286
+ argumentCount: knownArgumentCount ?? null,
2287
+ scope: "any",
2288
+ useFile: receiverDef.file,
2289
+ keepUniqueArityMismatch: true,
2290
+ });
2291
+ return selected.status === "unique" ? selected.member : undefined;
1994
2292
  }
1995
2293
  }
1996
2294
  return undefined;
@@ -2010,108 +2308,55 @@ function findLocalsWithinNode(locals, member, node, normalizeIdentifier = (name)
2010
2308
  (!predicate || predicate(local)));
2011
2309
  });
2012
2310
  }
2013
- function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name, predicate) {
2014
- return findLocalsWithinNode(locals, member, node, normalizeIdentifier, predicate)[0];
2015
- }
2016
2311
  function matchesReceiverMemberScope(local, memberScope, targetContext, container) {
2017
2312
  if (memberScope === "any")
2018
2313
  return true;
2019
2314
  return hasStaticModifier(local, targetContext, container) === (memberScope === "static");
2020
2315
  }
2021
- async function getCallableArityForDef(index, def) {
2022
- const context = await ensureParsedContext(def.file, undefined, index.languageExtensions);
2023
- const start = def.range.start;
2024
- const position = { row: start.line - 1, column: start.column - 1 };
2025
- const nameNode = context.tree.rootNode.descendantForPosition(position, position);
2026
- const container = nearestMemberContainer(nameNode);
2027
- let current = nameNode;
2028
- while (current && current !== container) {
2029
- if (CALLABLE_DECLARATION_NODE_TYPES[current.type]) {
2030
- const range = getCallableArity({
2031
- languageId: context.sup.id,
2032
- source: context.source,
2033
- declaration: current,
2034
- binding: memberLookupBinding(context.sup.id),
2035
- });
2036
- if (range)
2037
- return range;
2038
- }
2039
- current = current.parent;
2040
- }
2041
- return undefined;
2042
- }
2043
2316
  /**
2044
2317
  * Whether a member found for a receiverless call can accept that call's argument count. Unknown
2045
2318
  * counts and unknown arities accept.
2046
2319
  */
2047
- export async function memberAcceptsCallAt(index, member, callee, source, languageId) {
2320
+ export function memberAcceptsCallAt(index, member, callee, source, languageId) {
2048
2321
  const argumentCount = getCallArgumentCount({ languageId, source, call: callee.parent ?? callee });
2049
2322
  if (argumentCount === null)
2050
2323
  return true;
2051
- return (await receiverMemberAcceptsArgumentCount(index, member, argumentCount)) !== false;
2324
+ return receiverMemberAcceptsArgumentCount(index, member, argumentCount) !== false;
2052
2325
  }
2053
- async function receiverMemberAcceptsArgumentCount(index, def, argumentCount) {
2054
- const context = await ensureParsedContext(def.file, undefined, index.languageExtensions);
2055
- const start = def.range.start;
2056
- const position = {
2057
- row: start.line - 1,
2058
- column: start.column - 1,
2059
- };
2060
- const nameNode = context.tree.rootNode.descendantForPosition(position, position);
2061
- if (context.sup.id === "cpp") {
2062
- const shape = cppCallableShapeForNode(nameNode);
2063
- return shape
2064
- ? argumentCount >= shape.minArity && (shape.maxArity === null || argumentCount <= shape.maxArity)
2065
- : undefined;
2066
- }
2067
- const range = await getCallableArityForDef(index, def);
2326
+ function receiverMemberAcceptsArgumentCount(index, def, argumentCount) {
2327
+ const languageId = supportForFileWithoutHeaderSample(def.file, index.languageExtensions)?.id;
2328
+ if (!languageId)
2329
+ return undefined;
2330
+ const callable = def.callable ??
2331
+ index.byFile
2332
+ .get(fileIdentityKey(def.file))
2333
+ ?.locals.find((local) => local.range.start.index === def.range.start.index && local.localName === def.localName)
2334
+ ?.callable;
2335
+ const range = memberLookupBinding(languageId) === "unbound" ? (callable?.unboundArity ?? callable?.arity) : callable?.arity;
2068
2336
  if (!range)
2069
2337
  return undefined;
2070
2338
  return argumentCount >= range.minArgs && (range.maxArgs === null || argumentCount <= range.maxArgs);
2071
2339
  }
2072
- function uniqueReceiverMemberCandidates(candidates) {
2073
- const seen = new Set();
2074
- const unique = [];
2075
- for (const candidate of candidates) {
2076
- const key = keywordClassKey(candidate);
2077
- if (seen.has(key))
2078
- continue;
2079
- seen.add(key);
2080
- unique.push(candidate);
2081
- }
2082
- return unique;
2083
- }
2084
- async function selectReceiverMemberCandidates(index, candidates, knownArgumentCount, allowUniqueArityMismatch = true) {
2085
- if (candidates.length > 1) {
2086
- const file = candidates[0]?.file;
2087
- if (file && candidates.every((candidate) => candidate.file === file)) {
2088
- const context = await ensureParsedContext(file, undefined, index.languageExtensions);
2089
- if (isJsTsLanguage(context.sup.id)) {
2090
- // Signature-only overloads still need arity selection before generic member deduplication.
2091
- return typescriptSelectOverloadCandidate({
2092
- group: candidates,
2093
- tree: context.tree,
2094
- definitionOf: (candidate) => candidate,
2095
- declarationOf: (candidate) => nameNodeForDef(context, candidate)?.parent,
2096
- source: context.source,
2097
- languageId: context.sup.id,
2098
- argumentCount: knownArgumentCount ?? null,
2099
- });
2100
- }
2101
- }
2102
- }
2103
- const unique = uniqueReceiverMemberCandidates(candidates);
2104
- if (unique.length === 1 && (allowUniqueArityMismatch || knownArgumentCount === undefined))
2105
- return unique[0];
2106
- if (knownArgumentCount === undefined)
2107
- return undefined;
2108
- const matches = [];
2109
- for (const candidate of unique) {
2110
- if ((await receiverMemberAcceptsArgumentCount(index, candidate, knownArgumentCount)) !== false) {
2111
- matches.push(candidate);
2112
- }
2113
- }
2114
- return matches.length === 1 ? matches[0] : undefined;
2340
+ /** Indexed owner membership and callable facts for direct and merged-owner lookup. */
2341
+ function indexedMemberModel(index, members, languageId) {
2342
+ return {
2343
+ ownerKey: keywordClassKey,
2344
+ members: () => members,
2345
+ supertypes: () => [],
2346
+ name: (def) => def.localName,
2347
+ key: (def) => def.callable?.key ?? keywordClassKey(def),
2348
+ callable: (def) => {
2349
+ const facts = def.callable ??
2350
+ index.byFile
2351
+ .get(fileIdentityKey(def.file))
2352
+ ?.locals.find((local) => local.range.start.index === def.range.start.index && local.localName === def.localName)?.callable;
2353
+ if (!facts || memberLookupBinding(languageId) !== "unbound" || !facts.unboundArity)
2354
+ return facts;
2355
+ return { ...facts, arity: facts.unboundArity };
2356
+ },
2357
+ scope: () => "any",
2358
+ visible: () => true,
2359
+ };
2115
2360
  }
2116
2361
  function hasStaticModifier(local, targetContext, container) {
2117
2362
  const position = {
@@ -2208,9 +2453,6 @@ function findDirectLocalsWithinNode(locals, member, container, targetContext, no
2208
2453
  }
2209
2454
  return matches;
2210
2455
  }
2211
- function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier, predicate) {
2212
- return findDirectLocalsWithinNode(locals, member, container, targetContext, normalizeIdentifier, predicate)[0];
2213
- }
2214
2456
  function appendDirectKeywordMembers(locals, member, container, targetContext, normalizeIdentifier, predicate, matches) {
2215
2457
  const containerStart = container.startIndex;
2216
2458
  const containerEnd = container.endIndex;
@@ -2336,6 +2578,67 @@ function findRustImplsForType(root, typeName, source, sup) {
2336
2578
  visit(root);
2337
2579
  return found;
2338
2580
  }
2581
+ async function selectRustReceiverMember(index, receiverDef, member, context, locals, knownArgumentCount) {
2582
+ const inherent = [];
2583
+ const implemented = [];
2584
+ const traitMembers = new Map();
2585
+ const traitOwners = [];
2586
+ const module = index.byFile.get(fileIdentityKey(receiverDef.file));
2587
+ if (!module)
2588
+ return undefined;
2589
+ for (const impl of findRustImplsForType(context.tree.rootNode, receiverDef.localName, context.source, context.sup)) {
2590
+ const self = rustImplSelfTypeNode(impl, context.sup);
2591
+ const trait = impl.namedChildren.find((child) => child.type === "type_identifier" && child.id !== self?.id);
2592
+ const target = trait ? implemented : inherent;
2593
+ appendDirectKeywordMembers(locals, member, impl, context, context.sup.normalizeIdentifier, undefined, target);
2594
+ if (!trait)
2595
+ continue;
2596
+ const traitName = sliceText(trait, context.source);
2597
+ const traitDef = resolveNamedMemberContainer(index, module, traitName, context.sup.normalizeIdentifier);
2598
+ if (!traitDef)
2599
+ continue;
2600
+ const ref = await keywordClassRefFromDef(index, traitDef);
2601
+ if (!ref || ref.container.type !== "trait_item")
2602
+ continue;
2603
+ const key = keywordClassKey(traitDef);
2604
+ if (traitMembers.has(key))
2605
+ continue;
2606
+ const matches = [];
2607
+ appendDirectKeywordMembers(ref.module.locals, member, ref.container, ref.context, ref.context.sup.normalizeIdentifier, undefined, matches);
2608
+ traitMembers.set(key, matches);
2609
+ traitOwners.push(key);
2610
+ }
2611
+ const model = {
2612
+ ownerKey: (owner) => owner,
2613
+ members: (owner) => {
2614
+ if (owner === "inherent")
2615
+ return inherent;
2616
+ if (owner === "implemented")
2617
+ return implemented;
2618
+ return traitMembers.get(owner) ?? [];
2619
+ },
2620
+ supertypes: (owner) => {
2621
+ if (owner === "type")
2622
+ return ["inherent"];
2623
+ if (owner === "inherent")
2624
+ return ["implemented"];
2625
+ return owner === "implemented" ? traitOwners : [];
2626
+ },
2627
+ name: (def) => context.sup.normalizeIdentifier(def.localName),
2628
+ key: (def) => def.callable?.key ?? keywordClassKey(def),
2629
+ callable: (def) => def.callable,
2630
+ scope: () => "any",
2631
+ visible: () => true,
2632
+ };
2633
+ const selected = selectMember(["type"], model, {
2634
+ name: context.sup.normalizeIdentifier(member),
2635
+ argumentCount: knownArgumentCount ?? null,
2636
+ scope: "any",
2637
+ useFile: receiverDef.file,
2638
+ keepUniqueArityMismatch: true,
2639
+ });
2640
+ return selected.status === "unique" ? selected.member : undefined;
2641
+ }
2339
2642
  function goMethodReceiverTypeName(methodNode, source, sup) {
2340
2643
  const receiver = methodNode.childForFieldName("receiver");
2341
2644
  if (!receiver)
@@ -2397,9 +2700,10 @@ function goMethodsNamedOnType(locals, member, typeName, targetContext, normalize
2397
2700
  if (node.type === "method_declaration") {
2398
2701
  const receiverType = goMethodReceiverTypeName(node, targetContext.source, targetContext.sup);
2399
2702
  if (receiverType && normalizeIdentifier(receiverType) === normalizeIdentifier(typeName)) {
2400
- const local = findLocalWithinNode(locals, member, node, normalizeIdentifier);
2401
- if (local && !matches.includes(local))
2402
- matches.push(local);
2703
+ for (const local of findLocalsWithinNode(locals, member, node, normalizeIdentifier)) {
2704
+ if (!matches.includes(local))
2705
+ matches.push(local);
2706
+ }
2403
2707
  }
2404
2708
  return;
2405
2709
  }
@@ -2422,9 +2726,10 @@ function kotlinExtensionFunctionsNamedOnType(locals, member, typeName, targetCon
2422
2726
  if (node.type === "function_declaration") {
2423
2727
  const receiverType = kotlinExtensionReceiverTypeNode(node, targetContext.sup);
2424
2728
  if (receiverType && normalizeIdentifier(sliceText(receiverType, targetContext.source)) === normalizedType) {
2425
- const local = findLocalWithinNode(locals, member, node, normalizeIdentifier);
2426
- if (local && !matches.includes(local))
2427
- matches.push(local);
2729
+ for (const local of findLocalsWithinNode(locals, member, node, normalizeIdentifier)) {
2730
+ if (!matches.includes(local))
2731
+ matches.push(local);
2732
+ }
2428
2733
  }
2429
2734
  return;
2430
2735
  }
@@ -2434,50 +2739,79 @@ function kotlinExtensionFunctionsNamedOnType(locals, member, typeName, targetCon
2434
2739
  visit(targetContext.tree.rootNode);
2435
2740
  return matches;
2436
2741
  }
2437
- function findGoReceiverMember(locals, member, typeName, targetContext, normalizeIdentifier) {
2438
- const visited = new Set();
2439
- let level = [typeName];
2742
+ async function selectGoReceiverMember(index, receiverDef, member, normalizeIdentifier, knownArgumentCount) {
2743
+ const peers = getCompilationUnitPeers(index, receiverDef.file).files;
2744
+ const files = await Promise.all([...peers].map(async (file) => {
2745
+ const module = index.byFile.get(fileIdentityKey(file));
2746
+ if (!module)
2747
+ return null;
2748
+ const context = await ensureParsedContext(file, index.parsed?.get(fileIdentityKey(file)), index.languageExtensions);
2749
+ return context.sup.id === "go" ? { module, context } : null;
2750
+ }));
2751
+ const contexts = files.filter((file) => file !== null);
2752
+ const members = new Map();
2753
+ const embedded = new Map();
2754
+ const seen = new Set();
2755
+ let level = [receiverDef.localName];
2440
2756
  for (let depth = 0; depth < RECEIVER_HIERARCHY_DEPTH && level.length; depth += 1) {
2441
- const matches = [];
2442
2757
  const next = [];
2443
- for (const currentType of level) {
2444
- if (visited.has(currentType))
2758
+ for (const typeName of level) {
2759
+ if (seen.has(typeName))
2445
2760
  continue;
2446
- visited.add(currentType);
2447
- for (const method of goMethodsNamedOnType(locals, member, currentType, targetContext, normalizeIdentifier)) {
2448
- if (!matches.includes(method))
2449
- matches.push(method);
2450
- }
2451
- for (const embedded of goEmbeddedTypeNames(currentType, targetContext, normalizeIdentifier)) {
2452
- if (!visited.has(embedded) && !next.includes(embedded))
2453
- next.push(embedded);
2761
+ seen.add(typeName);
2762
+ const matches = [];
2763
+ const bases = [];
2764
+ for (const { module, context } of contexts) {
2765
+ const normalize = context.sup.normalizeIdentifier;
2766
+ matches.push(...goMethodsNamedOnType(module.locals, member, typeName, context, normalize));
2767
+ const spec = goTypeSpecNamed(context.tree.rootNode, typeName, context.source, normalize);
2768
+ if (!spec)
2769
+ continue;
2770
+ matches.push(...findDirectLocalsWithinNode(module.locals, member, spec, context, normalize).filter((def) => def.isMember));
2771
+ for (const base of goEmbeddedTypeNames(typeName, context, normalize)) {
2772
+ if (!bases.includes(base))
2773
+ bases.push(base);
2774
+ if (!seen.has(base) && !next.includes(base))
2775
+ next.push(base);
2776
+ }
2454
2777
  }
2778
+ members.set(typeName, matches);
2779
+ embedded.set(typeName, bases);
2455
2780
  }
2456
- if (matches.length === 1)
2457
- return matches[0];
2458
- if (matches.length > 1)
2459
- return undefined;
2460
2781
  level = next;
2461
2782
  }
2462
- return undefined;
2783
+ const model = {
2784
+ ownerKey: (owner) => owner,
2785
+ members: (owner) => members.get(owner) ?? [],
2786
+ supertypes: (owner) => embedded.get(owner) ?? [],
2787
+ name: (def) => normalizeIdentifier(def.localName),
2788
+ key: (def) => def.callable?.key ?? keywordClassKey(def),
2789
+ callable: (def) => def.callable,
2790
+ scope: () => "any",
2791
+ visible: () => true,
2792
+ };
2793
+ const selected = selectMember([receiverDef.localName], model, {
2794
+ name: normalizeIdentifier(member),
2795
+ argumentCount: knownArgumentCount ?? null,
2796
+ scope: "any",
2797
+ useFile: receiverDef.file,
2798
+ keepUniqueArityMismatch: true,
2799
+ });
2800
+ return selected.status === "unique" ? selected.member : undefined;
2463
2801
  }
2464
2802
  function pythonClassKey(def) {
2465
2803
  const start = def.range.start;
2466
2804
  return `${fileIdentityKey(def.file)}:${start.index ?? `${start.line}:${start.column}`}`;
2467
2805
  }
2468
- async function resolvePythonReceiverMember(index, mod, node, obj, member, source, tree, sup, resolveExpression) {
2469
- const classRef = await pythonReceiverClassRef(index, mod, node, obj, source, tree, sup, resolveExpression);
2806
+ async function resolvePythonReceiverMember(index, mod, node, obj, member, source, sup, resolveExpression, proof) {
2807
+ const classRef = await pythonReceiverClassRef(index, mod, node, obj, source, sup, resolveExpression, proof);
2470
2808
  if (!classRef)
2471
2809
  return undefined;
2472
2810
  return lookupPythonClassMember(index, classRef.ref, member, classRef.startAtSupertype);
2473
2811
  }
2474
- async function pythonReceiverClassRef(index, mod, node, obj, source, tree, sup, resolveExpression) {
2475
- const receiverName = receiverKeywordText(sup, obj, source, (callee) => {
2476
- const scope = getOrBuildScopeIndex(index, mod.file, source, sup, mod, tree);
2477
- return !!findClosestScopeBinding(scope, sliceText(callee, source), callee, sup);
2478
- });
2479
- const keywordKind = keywordReceiverKind(sup.id, receiverName);
2480
- if (keywordKind) {
2812
+ async function pythonReceiverClassRef(index, mod, node, obj, source, sup, resolveExpression, proof) {
2813
+ const receiver = proof ?? classifyReceiver(sup, obj, source, null, 0, obj.parent ?? obj, noLexicalBinding);
2814
+ if (receiver.kind === "own-type" || receiver.kind === "supertype") {
2481
2815
  const container = findEnclosingClassContainer(node);
2482
2816
  if (!container)
2483
2817
  return null;
@@ -2498,10 +2832,10 @@ async function pythonReceiverClassRef(index, mod, node, obj, source, tree, sup,
2498
2832
  if (!def)
2499
2833
  return null;
2500
2834
  const ref = await pythonClassRefFromDef(index, def);
2501
- return ref ? { ref, startAtSupertype: keywordKind === "supertype" } : null;
2835
+ return ref ? { ref, startAtSupertype: receiver.kind === "supertype" } : null;
2502
2836
  }
2503
2837
  let classDef;
2504
- const constructor = receiverConstructorExpression(obj, source, sup);
2838
+ const constructor = receiver.kind === "named-type" && receiver.proof !== "static-type" ? receiver.typeNode : null;
2505
2839
  if (constructor) {
2506
2840
  const result = await resolveExpression(constructor);
2507
2841
  if (result?.kind === "resolved" && result.def.kind === SymbolKind.Class) {
@@ -2539,13 +2873,13 @@ async function pythonClassRefFromDef(index, def) {
2539
2873
  }
2540
2874
  function pythonMembersOnClass(classRef, member) {
2541
2875
  const normalizeIdentifier = classRef.context.sup.normalizeIdentifier;
2542
- const direct = findDirectLocalWithinNode(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
2543
- if (direct)
2544
- return [direct];
2545
- const attribute = findPythonInstanceAttributeWithinClass(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
2546
- return attribute ? [attribute] : [];
2876
+ const direct = findDirectLocalsWithinNode(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
2877
+ if (direct.length)
2878
+ return direct;
2879
+ return findPythonInstanceAttributesWithinClass(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
2547
2880
  }
2548
- function findPythonInstanceAttributeWithinClass(locals, member, container, targetContext, normalizeIdentifier) {
2881
+ function findPythonInstanceAttributesWithinClass(locals, member, container, targetContext, normalizeIdentifier) {
2882
+ const matches = [];
2549
2883
  const containerStart = container.startIndex;
2550
2884
  const containerEnd = container.endIndex;
2551
2885
  const normalizedMember = normalizeIdentifier(member);
@@ -2566,9 +2900,9 @@ function findPythonInstanceAttributeWithinClass(locals, member, container, targe
2566
2900
  };
2567
2901
  const nameNode = targetContext.tree.rootNode.descendantForPosition(position, position);
2568
2902
  if (isPythonReceiverAttributeAssignmentName(nameNode))
2569
- return local;
2903
+ matches.push(local);
2570
2904
  }
2571
- return undefined;
2905
+ return matches;
2572
2906
  }
2573
2907
  function pythonBaseIdentifierNodes(classNode) {
2574
2908
  const bases = classNode.childForFieldName("superclasses") ??
@@ -2638,34 +2972,25 @@ async function pythonBaseClassRefs(index, classRef) {
2638
2972
  return refs;
2639
2973
  }
2640
2974
  async function lookupPythonClassMember(index, start, member, startAtSupertype = false) {
2641
- if (!startAtSupertype) {
2642
- const own = pythonMembersOnClass(start, member);
2643
- if (own.length === 1)
2644
- return own[0];
2645
- if (own.length > 1)
2646
- return undefined;
2647
- }
2648
- let level = await pythonBaseClassRefs(index, start);
2649
- const visited = new Set([pythonClassKey(start.def), ...level.map((base) => pythonClassKey(base.def))]);
2975
+ const membersByOwner = new Map();
2976
+ const parentsByOwner = new Map();
2977
+ const visited = new Set([pythonClassKey(start.def)]);
2978
+ let level = [start];
2650
2979
  for (let depth = 0; depth < RECEIVER_HIERARCHY_DEPTH && level.length; depth += 1) {
2651
- const matches = [];
2652
- const seenMatch = new Set();
2653
- for (const base of level) {
2654
- for (const hit of pythonMembersOnClass(base, member)) {
2655
- const key = pythonClassKey(hit);
2656
- if (seenMatch.has(key))
2657
- continue;
2658
- seenMatch.add(key);
2659
- matches.push(hit);
2660
- }
2661
- }
2662
- if (matches.length === 1)
2663
- return matches[0];
2664
- if (matches.length > 1)
2665
- return undefined;
2980
+ let named = false;
2981
+ for (const ref of level) {
2982
+ const members = startAtSupertype && !depth ? [] : pythonMembersOnClass(ref, member);
2983
+ membersByOwner.set(pythonClassKey(ref.def), members);
2984
+ if (members.length)
2985
+ named = true;
2986
+ }
2987
+ if (named)
2988
+ break;
2666
2989
  const next = [];
2667
- for (const base of level) {
2668
- for (const parent of await pythonBaseClassRefs(index, base)) {
2990
+ for (const ref of level) {
2991
+ const parents = await pythonBaseClassRefs(index, ref);
2992
+ parentsByOwner.set(pythonClassKey(ref.def), parents);
2993
+ for (const parent of parents) {
2669
2994
  const key = pythonClassKey(parent.def);
2670
2995
  if (visited.has(key))
2671
2996
  continue;
@@ -2675,6 +3000,23 @@ async function lookupPythonClassMember(index, start, member, startAtSupertype =
2675
3000
  }
2676
3001
  level = next;
2677
3002
  }
2678
- return undefined;
3003
+ const model = {
3004
+ ownerKey: (ref) => pythonClassKey(ref.def),
3005
+ members: (ref) => membersByOwner.get(pythonClassKey(ref.def)) ?? [],
3006
+ supertypes: (ref) => parentsByOwner.get(pythonClassKey(ref.def)) ?? [],
3007
+ name: (def) => def.localName,
3008
+ key: (def) => def.callable?.key ?? pythonClassKey(def),
3009
+ callable: (def) => def.callable,
3010
+ scope: () => "any",
3011
+ visible: () => true,
3012
+ };
3013
+ const selected = selectMember([start], model, {
3014
+ name: member,
3015
+ argumentCount: null,
3016
+ scope: "any",
3017
+ useFile: start.def.file,
3018
+ startAtAncestor: startAtSupertype,
3019
+ });
3020
+ return selected.status === "unique" ? selected.member : undefined;
2679
3021
  }
2680
3022
  //# sourceMappingURL=navigation-goto.js.map