@lzehrung/codegraph 3.0.1 → 3.1.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 (684) hide show
  1. package/README.md +17 -17
  2. package/codegraph-skill/codegraph/SKILL.md +6 -2
  3. package/dist/agent/artifact.d.ts.map +1 -1
  4. package/dist/agent/artifact.js +4 -9
  5. package/dist/agent/artifact.js.map +1 -1
  6. package/dist/agent/call-hierarchy.d.ts +4 -2
  7. package/dist/agent/call-hierarchy.d.ts.map +1 -1
  8. package/dist/agent/call-hierarchy.js +20 -29
  9. package/dist/agent/call-hierarchy.js.map +1 -1
  10. package/dist/agent/explain.d.ts.map +1 -1
  11. package/dist/agent/explain.js +24 -18
  12. package/dist/agent/explain.js.map +1 -1
  13. package/dist/agent/explore.d.ts.map +1 -1
  14. package/dist/agent/explore.js +2 -11
  15. package/dist/agent/explore.js.map +1 -1
  16. package/dist/agent/file-view.d.ts.map +1 -1
  17. package/dist/agent/file-view.js +4 -12
  18. package/dist/agent/file-view.js.map +1 -1
  19. package/dist/agent/normalize.d.ts +0 -3
  20. package/dist/agent/normalize.d.ts.map +1 -1
  21. package/dist/agent/normalize.js +1 -7
  22. package/dist/agent/normalize.js.map +1 -1
  23. package/dist/agent/orient.d.ts.map +1 -1
  24. package/dist/agent/orient.js +2 -6
  25. package/dist/agent/orient.js.map +1 -1
  26. package/dist/agent/packet.d.ts.map +1 -1
  27. package/dist/agent/packet.js +2 -5
  28. package/dist/agent/packet.js.map +1 -1
  29. package/dist/agent/query-index/content.d.ts.map +1 -1
  30. package/dist/agent/query-index/content.js +2 -6
  31. package/dist/agent/query-index/content.js.map +1 -1
  32. package/dist/agent/query-index/update.d.ts.map +1 -1
  33. package/dist/agent/query-index/update.js +8 -45
  34. package/dist/agent/query-index/update.js.map +1 -1
  35. package/dist/agent/query-index/worker-pool.d.ts.map +1 -1
  36. package/dist/agent/query-index/worker-pool.js +2 -1
  37. package/dist/agent/query-index/worker-pool.js.map +1 -1
  38. package/dist/agent/refactor-plan.d.ts +2 -2
  39. package/dist/agent/refactor-plan.d.ts.map +1 -1
  40. package/dist/agent/refactor-plan.js +11 -57
  41. package/dist/agent/refactor-plan.js.map +1 -1
  42. package/dist/agent/rename-preview.d.ts.map +1 -1
  43. package/dist/agent/rename-preview.js +166 -23
  44. package/dist/agent/rename-preview.js.map +1 -1
  45. package/dist/agent/search.d.ts +13 -0
  46. package/dist/agent/search.d.ts.map +1 -1
  47. package/dist/agent/search.js +17 -26
  48. package/dist/agent/search.js.map +1 -1
  49. package/dist/agent/semantic-symbols.d.ts +1 -1
  50. package/dist/agent/semantic-symbols.d.ts.map +1 -1
  51. package/dist/agent/semantic-symbols.js +2 -5
  52. package/dist/agent/semantic-symbols.js.map +1 -1
  53. package/dist/agent/semantic.d.ts +5 -0
  54. package/dist/agent/semantic.d.ts.map +1 -1
  55. package/dist/agent/semantic.js +12 -1
  56. package/dist/agent/semantic.js.map +1 -1
  57. package/dist/agent/session.d.ts +9 -0
  58. package/dist/agent/session.d.ts.map +1 -1
  59. package/dist/agent/session.js +59 -41
  60. package/dist/agent/session.js.map +1 -1
  61. package/dist/agent/type-hierarchy.d.ts +4 -2
  62. package/dist/agent/type-hierarchy.d.ts.map +1 -1
  63. package/dist/agent/type-hierarchy.js +19 -31
  64. package/dist/agent/type-hierarchy.js.map +1 -1
  65. package/dist/agent/workspace-symbols.d.ts +1 -1
  66. package/dist/agent/workspace-symbols.d.ts.map +1 -1
  67. package/dist/agent/workspace-symbols.js +7 -15
  68. package/dist/agent/workspace-symbols.js.map +1 -1
  69. package/dist/analysis-summary.d.ts +1 -4
  70. package/dist/analysis-summary.d.ts.map +1 -1
  71. package/dist/analysis-summary.js +58 -19
  72. package/dist/analysis-summary.js.map +1 -1
  73. package/dist/bin/cli.js +41060 -27641
  74. package/dist/bin/query-index-worker.js +268 -241
  75. package/dist/bootstrap/tree-sitter-languages.d.ts +2 -0
  76. package/dist/bootstrap/tree-sitter-languages.d.ts.map +1 -1
  77. package/dist/bootstrap/tree-sitter-languages.js +6 -19
  78. package/dist/bootstrap/tree-sitter-languages.js.map +1 -1
  79. package/dist/chunking/chunk-matches.d.ts.map +1 -1
  80. package/dist/chunking/chunk-matches.js +6 -42
  81. package/dist/chunking/chunk-matches.js.map +1 -1
  82. package/dist/chunking/chunk-split.d.ts +7 -0
  83. package/dist/chunking/chunk-split.d.ts.map +1 -1
  84. package/dist/chunking/chunk-split.js +3 -3
  85. package/dist/chunking/chunk-split.js.map +1 -1
  86. package/dist/chunking/chunk-text-file.js +2 -30
  87. package/dist/chunking/chunk-text-file.js.map +1 -1
  88. package/dist/cli/affected.d.ts.map +1 -1
  89. package/dist/cli/affected.js +1 -9
  90. package/dist/cli/affected.js.map +1 -1
  91. package/dist/cli/call-hierarchy.js +3 -6
  92. package/dist/cli/call-hierarchy.js.map +1 -1
  93. package/dist/cli/chunk.d.ts.map +1 -1
  94. package/dist/cli/chunk.js +4 -11
  95. package/dist/cli/chunk.js.map +1 -1
  96. package/dist/cli/command-table.d.ts.map +1 -1
  97. package/dist/cli/command-table.js +7 -0
  98. package/dist/cli/command-table.js.map +1 -1
  99. package/dist/cli/context.d.ts +1 -0
  100. package/dist/cli/context.d.ts.map +1 -1
  101. package/dist/cli/context.js +1 -1
  102. package/dist/cli/context.js.map +1 -1
  103. package/dist/cli/doctor.d.ts.map +1 -1
  104. package/dist/cli/doctor.js +1 -11
  105. package/dist/cli/doctor.js.map +1 -1
  106. package/dist/cli/duplicates.d.ts +5 -0
  107. package/dist/cli/duplicates.d.ts.map +1 -1
  108. package/dist/cli/duplicates.js +15 -2
  109. package/dist/cli/duplicates.js.map +1 -1
  110. package/dist/cli/graph.d.ts +4 -12
  111. package/dist/cli/graph.d.ts.map +1 -1
  112. package/dist/cli/graph.js +17 -8
  113. package/dist/cli/graph.js.map +1 -1
  114. package/dist/cli/help.d.ts +4 -4
  115. package/dist/cli/help.d.ts.map +1 -1
  116. package/dist/cli/help.js +17 -9
  117. package/dist/cli/help.js.map +1 -1
  118. package/dist/cli/index.d.ts +2 -12
  119. package/dist/cli/index.d.ts.map +1 -1
  120. package/dist/cli/index.js +2 -5
  121. package/dist/cli/index.js.map +1 -1
  122. package/dist/cli/links.d.ts.map +1 -1
  123. package/dist/cli/links.js +4 -10
  124. package/dist/cli/links.js.map +1 -1
  125. package/dist/cli/mcp.d.ts.map +1 -1
  126. package/dist/cli/mcp.js +5 -0
  127. package/dist/cli/mcp.js.map +1 -1
  128. package/dist/cli/module-locals.d.ts +8 -0
  129. package/dist/cli/module-locals.d.ts.map +1 -0
  130. package/dist/cli/module-locals.js +9 -0
  131. package/dist/cli/module-locals.js.map +1 -0
  132. package/dist/cli/navigation.d.ts +2 -0
  133. package/dist/cli/navigation.d.ts.map +1 -1
  134. package/dist/cli/navigation.js +3 -5
  135. package/dist/cli/navigation.js.map +1 -1
  136. package/dist/cli/options.d.ts.map +1 -1
  137. package/dist/cli/options.js +6 -1
  138. package/dist/cli/options.js.map +1 -1
  139. package/dist/cli/pretty.d.ts +1 -0
  140. package/dist/cli/pretty.d.ts.map +1 -1
  141. package/dist/cli/pretty.js +6 -8
  142. package/dist/cli/pretty.js.map +1 -1
  143. package/dist/cli/progress.d.ts.map +1 -1
  144. package/dist/cli/progress.js +42 -16
  145. package/dist/cli/progress.js.map +1 -1
  146. package/dist/cli/refactor-plan.js +2 -5
  147. package/dist/cli/refactor-plan.js.map +1 -1
  148. package/dist/cli/rename-preview.js +2 -5
  149. package/dist/cli/rename-preview.js.map +1 -1
  150. package/dist/cli/review.d.ts +6 -16
  151. package/dist/cli/review.d.ts.map +1 -1
  152. package/dist/cli/review.js +2 -0
  153. package/dist/cli/review.js.map +1 -1
  154. package/dist/cli/server.d.ts.map +1 -1
  155. package/dist/cli/server.js +9 -10
  156. package/dist/cli/server.js.map +1 -1
  157. package/dist/cli/type-hierarchy.js +8 -8
  158. package/dist/cli/type-hierarchy.js.map +1 -1
  159. package/dist/cli/viewer.js +1 -1
  160. package/dist/cli/viewer.js.map +1 -1
  161. package/dist/document-links/asciidoc.d.ts.map +1 -1
  162. package/dist/document-links/asciidoc.js +4 -16
  163. package/dist/document-links/asciidoc.js.map +1 -1
  164. package/dist/document-links/check.d.ts.map +1 -1
  165. package/dist/document-links/check.js +1 -3
  166. package/dist/document-links/check.js.map +1 -1
  167. package/dist/document-links/html.d.ts.map +1 -1
  168. package/dist/document-links/html.js +6 -44
  169. package/dist/document-links/html.js.map +1 -1
  170. package/dist/document-links/markdown.d.ts.map +1 -1
  171. package/dist/document-links/markdown.js +4 -13
  172. package/dist/document-links/markdown.js.map +1 -1
  173. package/dist/document-links/rst.d.ts.map +1 -1
  174. package/dist/document-links/rst.js +7 -31
  175. package/dist/document-links/rst.js.map +1 -1
  176. package/dist/document-links/sfc.d.ts.map +1 -1
  177. package/dist/document-links/sfc.js +2 -5
  178. package/dist/document-links/sfc.js.map +1 -1
  179. package/dist/document-links/shared.d.ts +2 -0
  180. package/dist/document-links/shared.d.ts.map +1 -1
  181. package/dist/document-links/shared.js +13 -0
  182. package/dist/document-links/shared.js.map +1 -1
  183. package/dist/drift/artifact.d.ts.map +1 -1
  184. package/dist/drift/artifact.js +4 -27
  185. package/dist/drift/artifact.js.map +1 -1
  186. package/dist/drift/git.d.ts.map +1 -1
  187. package/dist/drift/git.js +10 -2
  188. package/dist/drift/git.js.map +1 -1
  189. package/dist/drift/graph-edges.d.ts +4 -0
  190. package/dist/drift/graph-edges.d.ts.map +1 -0
  191. package/dist/drift/graph-edges.js +15 -0
  192. package/dist/drift/graph-edges.js.map +1 -0
  193. package/dist/drift/snapshot.d.ts.map +1 -1
  194. package/dist/drift/snapshot.js +2 -17
  195. package/dist/drift/snapshot.js.map +1 -1
  196. package/dist/duplicates/candidates.d.ts +61 -0
  197. package/dist/duplicates/candidates.d.ts.map +1 -0
  198. package/dist/duplicates/candidates.js +873 -0
  199. package/dist/duplicates/candidates.js.map +1 -0
  200. package/dist/duplicates/progress.d.ts +17 -0
  201. package/dist/duplicates/progress.d.ts.map +1 -0
  202. package/dist/duplicates/progress.js +57 -0
  203. package/dist/duplicates/progress.js.map +1 -0
  204. package/dist/duplicates/scoring.d.ts +9 -40
  205. package/dist/duplicates/scoring.d.ts.map +1 -1
  206. package/dist/duplicates/scoring.js +34 -414
  207. package/dist/duplicates/scoring.js.map +1 -1
  208. package/dist/duplicates/types.d.ts +30 -1
  209. package/dist/duplicates/types.d.ts.map +1 -1
  210. package/dist/duplicates/unit-cache.d.ts +11 -1
  211. package/dist/duplicates/unit-cache.d.ts.map +1 -1
  212. package/dist/duplicates/unit-cache.js +20 -2
  213. package/dist/duplicates/unit-cache.js.map +1 -1
  214. package/dist/duplicates/units.d.ts +4 -2
  215. package/dist/duplicates/units.d.ts.map +1 -1
  216. package/dist/duplicates/units.js +47 -25
  217. package/dist/duplicates/units.js.map +1 -1
  218. package/dist/duplicates.d.ts +1 -0
  219. package/dist/duplicates.d.ts.map +1 -1
  220. package/dist/duplicates.js +116 -62
  221. package/dist/duplicates.js.map +1 -1
  222. package/dist/graph-builder.d.ts +1 -1
  223. package/dist/graph-builder.d.ts.map +1 -1
  224. package/dist/graph-builder.js +3 -2
  225. package/dist/graph-builder.js.map +1 -1
  226. package/dist/graph-edge-collector.d.ts +3 -1
  227. package/dist/graph-edge-collector.d.ts.map +1 -1
  228. package/dist/graph-edge-collector.js +38 -6
  229. package/dist/graph-edge-collector.js.map +1 -1
  230. package/dist/graphs/angularjs.d.ts.map +1 -1
  231. package/dist/graphs/angularjs.js +2 -9
  232. package/dist/graphs/angularjs.js.map +1 -1
  233. package/dist/graphs/edge-resolution.d.ts +4 -0
  234. package/dist/graphs/edge-resolution.d.ts.map +1 -1
  235. package/dist/graphs/edge-resolution.js +2 -0
  236. package/dist/graphs/edge-resolution.js.map +1 -1
  237. package/dist/graphs/external/manifests.d.ts.map +1 -1
  238. package/dist/graphs/external/manifests.js +1 -6
  239. package/dist/graphs/external/manifests.js.map +1 -1
  240. package/dist/graphs/specifiers.d.ts.map +1 -1
  241. package/dist/graphs/specifiers.js +47 -26
  242. package/dist/graphs/specifiers.js.map +1 -1
  243. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts +2 -0
  244. package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
  245. package/dist/graphs/symbol-graph-detailed/edge-passes.js +9 -3
  246. package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
  247. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +3 -3
  248. package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
  249. package/dist/graphs/symbol-graph-detailed/receiver-calls.js +2 -26
  250. package/dist/graphs/symbol-graph-detailed/receiver-calls.js.map +1 -1
  251. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  252. package/dist/graphs/symbol-graph-detailed.js +38 -1
  253. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  254. package/dist/impact/analyzer.d.ts.map +1 -1
  255. package/dist/impact/analyzer.js +23 -17
  256. package/dist/impact/analyzer.js.map +1 -1
  257. package/dist/impact/budgets.d.ts.map +1 -1
  258. package/dist/impact/budgets.js +3 -9
  259. package/dist/impact/budgets.js.map +1 -1
  260. package/dist/impact/call-compatibility.d.ts.map +1 -1
  261. package/dist/impact/call-compatibility.js +3 -12
  262. package/dist/impact/call-compatibility.js.map +1 -1
  263. package/dist/impact/context.d.ts +6 -0
  264. package/dist/impact/context.d.ts.map +1 -1
  265. package/dist/impact/context.js +2 -2
  266. package/dist/impact/context.js.map +1 -1
  267. package/dist/impact/direct.d.ts.map +1 -1
  268. package/dist/impact/direct.js +2 -6
  269. package/dist/impact/direct.js.map +1 -1
  270. package/dist/impact/map.d.ts +3 -1
  271. package/dist/impact/map.d.ts.map +1 -1
  272. package/dist/impact/map.js +12 -5
  273. package/dist/impact/map.js.map +1 -1
  274. package/dist/impact/providers/base.js +1 -1
  275. package/dist/impact/providers/base.js.map +1 -1
  276. package/dist/impact/reference-cache.d.ts.map +1 -1
  277. package/dist/impact/reference-cache.js +1 -24
  278. package/dist/impact/reference-cache.js.map +1 -1
  279. package/dist/impact/report-shared.d.ts +2 -1
  280. package/dist/impact/report-shared.d.ts.map +1 -1
  281. package/dist/impact/report-shared.js +10 -0
  282. package/dist/impact/report-shared.js.map +1 -1
  283. package/dist/impact/report-suggestions.d.ts.map +1 -1
  284. package/dist/impact/report-suggestions.js +2 -8
  285. package/dist/impact/report-suggestions.js.map +1 -1
  286. package/dist/impact/report.d.ts.map +1 -1
  287. package/dist/impact/report.js +2 -8
  288. package/dist/impact/report.js.map +1 -1
  289. package/dist/impact/streaming.d.ts.map +1 -1
  290. package/dist/impact/streaming.js +3 -8
  291. package/dist/impact/streaming.js.map +1 -1
  292. package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
  293. package/dist/indexer/build-cache/manifest.js +10 -108
  294. package/dist/indexer/build-cache/manifest.js.map +1 -1
  295. package/dist/indexer/build-cache/module-cache.d.ts +6 -1
  296. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  297. package/dist/indexer/build-cache/module-cache.js +25 -2
  298. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  299. package/dist/indexer/build-cache/options.d.ts +38 -1
  300. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  301. package/dist/indexer/build-cache/options.js +38 -1
  302. package/dist/indexer/build-cache/options.js.map +1 -1
  303. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  304. package/dist/indexer/build-cache/project-snapshot.js +48 -99
  305. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  306. package/dist/indexer/build-cache/reports.d.ts +1 -0
  307. package/dist/indexer/build-cache/reports.d.ts.map +1 -1
  308. package/dist/indexer/build-cache/reports.js +10 -0
  309. package/dist/indexer/build-cache/reports.js.map +1 -1
  310. package/dist/indexer/build-index.d.ts +2 -0
  311. package/dist/indexer/build-index.d.ts.map +1 -1
  312. package/dist/indexer/build-index.js +187 -57
  313. package/dist/indexer/build-index.js.map +1 -1
  314. package/dist/indexer/build-workers.d.ts +7 -1
  315. package/dist/indexer/build-workers.d.ts.map +1 -1
  316. package/dist/indexer/build-workers.js +12 -0
  317. package/dist/indexer/build-workers.js.map +1 -1
  318. package/dist/indexer/call-hierarchy.d.ts.map +1 -1
  319. package/dist/indexer/call-hierarchy.js +5 -17
  320. package/dist/indexer/call-hierarchy.js.map +1 -1
  321. package/dist/indexer/compilation-units.d.ts +32 -20
  322. package/dist/indexer/compilation-units.d.ts.map +1 -1
  323. package/dist/indexer/compilation-units.js +139 -145
  324. package/dist/indexer/compilation-units.js.map +1 -1
  325. package/dist/indexer/cpp-callables.d.ts.map +1 -1
  326. package/dist/indexer/cpp-callables.js +2 -7
  327. package/dist/indexer/cpp-callables.js.map +1 -1
  328. package/dist/indexer/import-types.d.ts +5 -0
  329. package/dist/indexer/import-types.d.ts.map +1 -1
  330. package/dist/indexer/import-types.js.map +1 -1
  331. package/dist/indexer/imports/binding-ranges.d.ts +5 -12
  332. package/dist/indexer/imports/binding-ranges.d.ts.map +1 -1
  333. package/dist/indexer/imports/binding-ranges.js +13 -19
  334. package/dist/indexer/imports/binding-ranges.js.map +1 -1
  335. package/dist/indexer/imports/context.d.ts +6 -0
  336. package/dist/indexer/imports/context.d.ts.map +1 -1
  337. package/dist/indexer/imports/import-binding-tables.d.ts +28 -13
  338. package/dist/indexer/imports/import-binding-tables.d.ts.map +1 -1
  339. package/dist/indexer/imports/import-binding-tables.js +179 -178
  340. package/dist/indexer/imports/import-binding-tables.js.map +1 -1
  341. package/dist/indexer/imports/js-text-imports.d.ts +0 -1
  342. package/dist/indexer/imports/js-text-imports.d.ts.map +1 -1
  343. package/dist/indexer/imports/js-text-imports.js +0 -176
  344. package/dist/indexer/imports/js-text-imports.js.map +1 -1
  345. package/dist/indexer/imports/language-specific.d.ts.map +1 -1
  346. package/dist/indexer/imports/language-specific.js +4 -8
  347. package/dist/indexer/imports/language-specific.js.map +1 -1
  348. package/dist/indexer/imports/python.d.ts +0 -1
  349. package/dist/indexer/imports/python.d.ts.map +1 -1
  350. package/dist/indexer/imports/python.js +1 -29
  351. package/dist/indexer/imports/python.js.map +1 -1
  352. package/dist/indexer/imports/text-import-extractors.d.ts +2 -9
  353. package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -1
  354. package/dist/indexer/imports/text-import-extractors.js +0 -284
  355. package/dist/indexer/imports/text-import-extractors.js.map +1 -1
  356. package/dist/indexer/imports.d.ts +15 -0
  357. package/dist/indexer/imports.d.ts.map +1 -1
  358. package/dist/indexer/imports.js +82 -44
  359. package/dist/indexer/imports.js.map +1 -1
  360. package/dist/indexer/incremental-plan.d.ts +0 -1
  361. package/dist/indexer/incremental-plan.d.ts.map +1 -1
  362. package/dist/indexer/incremental-plan.js +6 -12
  363. package/dist/indexer/incremental-plan.js.map +1 -1
  364. package/dist/indexer/name-lookup-policies/implicit-self.d.ts.map +1 -1
  365. package/dist/indexer/name-lookup-policies/implicit-self.js +25 -4
  366. package/dist/indexer/name-lookup-policies/implicit-self.js.map +1 -1
  367. package/dist/indexer/name-resolution-types.d.ts +5 -0
  368. package/dist/indexer/name-resolution-types.d.ts.map +1 -1
  369. package/dist/indexer/name-resolution.d.ts.map +1 -1
  370. package/dist/indexer/name-resolution.js +2 -0
  371. package/dist/indexer/name-resolution.js.map +1 -1
  372. package/dist/indexer/navigation-cpp.d.ts.map +1 -1
  373. package/dist/indexer/navigation-cpp.js +3 -5
  374. package/dist/indexer/navigation-cpp.js.map +1 -1
  375. package/dist/indexer/navigation-goto.d.ts +49 -3
  376. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  377. package/dist/indexer/navigation-goto.js +500 -106
  378. package/dist/indexer/navigation-goto.js.map +1 -1
  379. package/dist/indexer/navigation-local.d.ts +7 -0
  380. package/dist/indexer/navigation-local.d.ts.map +1 -1
  381. package/dist/indexer/navigation-local.js +22 -2
  382. package/dist/indexer/navigation-local.js.map +1 -1
  383. package/dist/indexer/navigation-php.d.ts +0 -1
  384. package/dist/indexer/navigation-php.d.ts.map +1 -1
  385. package/dist/indexer/navigation-php.js +1 -7
  386. package/dist/indexer/navigation-php.js.map +1 -1
  387. package/dist/indexer/navigation-references.d.ts +1 -0
  388. package/dist/indexer/navigation-references.d.ts.map +1 -1
  389. package/dist/indexer/navigation-references.js +134 -23
  390. package/dist/indexer/navigation-references.js.map +1 -1
  391. package/dist/indexer/navigation-resolve.d.ts +22 -0
  392. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  393. package/dist/indexer/navigation-resolve.js +73 -8
  394. package/dist/indexer/navigation-resolve.js.map +1 -1
  395. package/dist/indexer/navigation.d.ts +4 -1
  396. package/dist/indexer/navigation.d.ts.map +1 -1
  397. package/dist/indexer/navigation.js +398 -95
  398. package/dist/indexer/navigation.js.map +1 -1
  399. package/dist/indexer/python-property-decorator.d.ts +11 -0
  400. package/dist/indexer/python-property-decorator.d.ts.map +1 -0
  401. package/dist/indexer/python-property-decorator.js +30 -0
  402. package/dist/indexer/python-property-decorator.js.map +1 -0
  403. package/dist/indexer/shared-owner-identity.d.ts +3 -1
  404. package/dist/indexer/shared-owner-identity.d.ts.map +1 -1
  405. package/dist/indexer/shared-owner-identity.js +40 -12
  406. package/dist/indexer/shared-owner-identity.js.map +1 -1
  407. package/dist/indexer/shared.d.ts +10 -0
  408. package/dist/indexer/shared.d.ts.map +1 -1
  409. package/dist/indexer/shared.js +8 -0
  410. package/dist/indexer/shared.js.map +1 -1
  411. package/dist/indexer/star-import-precedence.d.ts +5 -1
  412. package/dist/indexer/star-import-precedence.d.ts.map +1 -1
  413. package/dist/indexer/star-import-precedence.js +12 -19
  414. package/dist/indexer/star-import-precedence.js.map +1 -1
  415. package/dist/indexer/type-hierarchy.d.ts.map +1 -1
  416. package/dist/indexer/type-hierarchy.js +8 -9
  417. package/dist/indexer/type-hierarchy.js.map +1 -1
  418. package/dist/indexer/types.d.ts +49 -1
  419. package/dist/indexer/types.d.ts.map +1 -1
  420. package/dist/indexer/types.js.map +1 -1
  421. package/dist/indexer/workspace-symbols.d.ts.map +1 -1
  422. package/dist/indexer/workspace-symbols.js +3 -13
  423. package/dist/indexer/workspace-symbols.js.map +1 -1
  424. package/dist/installer/locks.d.ts +1 -0
  425. package/dist/installer/locks.d.ts.map +1 -1
  426. package/dist/installer/locks.js +4 -8
  427. package/dist/installer/locks.js.map +1 -1
  428. package/dist/installer/registry.d.ts.map +1 -1
  429. package/dist/installer/registry.js +9 -15
  430. package/dist/installer/registry.js.map +1 -1
  431. package/dist/languages/callable-arity.d.ts.map +1 -1
  432. package/dist/languages/callable-arity.js +1 -38
  433. package/dist/languages/callable-arity.js.map +1 -1
  434. package/dist/languages/definitions/csharp.d.ts.map +1 -1
  435. package/dist/languages/definitions/csharp.js +5 -13
  436. package/dist/languages/definitions/csharp.js.map +1 -1
  437. package/dist/languages/definitions/java.d.ts.map +1 -1
  438. package/dist/languages/definitions/java.js +4 -13
  439. package/dist/languages/definitions/java.js.map +1 -1
  440. package/dist/languages/definitions/kotlin.d.ts.map +1 -1
  441. package/dist/languages/definitions/kotlin.js +4 -8
  442. package/dist/languages/definitions/kotlin.js.map +1 -1
  443. package/dist/languages/definitions/python.d.ts.map +1 -1
  444. package/dist/languages/definitions/python.js +5 -3
  445. package/dist/languages/definitions/python.js.map +1 -1
  446. package/dist/languages/import-statement-parsers.d.ts +0 -30
  447. package/dist/languages/import-statement-parsers.d.ts.map +1 -1
  448. package/dist/languages/import-statement-parsers.js +1 -81
  449. package/dist/languages/import-statement-parsers.js.map +1 -1
  450. package/dist/languages/sfc.d.ts.map +1 -1
  451. package/dist/languages/sfc.js +8 -43
  452. package/dist/languages/sfc.js.map +1 -1
  453. package/dist/lifecycle/manifest.d.ts.map +1 -1
  454. package/dist/lifecycle/manifest.js +11 -29
  455. package/dist/lifecycle/manifest.js.map +1 -1
  456. package/dist/mcp/cancellation.d.ts +6 -0
  457. package/dist/mcp/cancellation.d.ts.map +1 -0
  458. package/dist/mcp/cancellation.js +11 -0
  459. package/dist/mcp/cancellation.js.map +1 -0
  460. package/dist/mcp/handlers.d.ts +54 -3
  461. package/dist/mcp/handlers.d.ts.map +1 -1
  462. package/dist/mcp/handlers.js +186 -42
  463. package/dist/mcp/handlers.js.map +1 -1
  464. package/dist/mcp/http-transport.d.ts.map +1 -1
  465. package/dist/mcp/http-transport.js +9 -2
  466. package/dist/mcp/http-transport.js.map +1 -1
  467. package/dist/mcp/index-readiness.d.ts +114 -0
  468. package/dist/mcp/index-readiness.d.ts.map +1 -0
  469. package/dist/mcp/index-readiness.js +264 -0
  470. package/dist/mcp/index-readiness.js.map +1 -0
  471. package/dist/mcp/project-watcher.d.ts +125 -0
  472. package/dist/mcp/project-watcher.d.ts.map +1 -0
  473. package/dist/mcp/project-watcher.js +643 -0
  474. package/dist/mcp/project-watcher.js.map +1 -0
  475. package/dist/mcp/protocol.d.ts.map +1 -1
  476. package/dist/mcp/protocol.js +23 -10
  477. package/dist/mcp/protocol.js.map +1 -1
  478. package/dist/mcp/server.d.ts +2 -0
  479. package/dist/mcp/server.d.ts.map +1 -1
  480. package/dist/mcp/server.js +11 -2
  481. package/dist/mcp/server.js.map +1 -1
  482. package/dist/mcp/stale-install.d.ts +13 -0
  483. package/dist/mcp/stale-install.d.ts.map +1 -0
  484. package/dist/mcp/stale-install.js +30 -0
  485. package/dist/mcp/stale-install.js.map +1 -0
  486. package/dist/native/byte-index.d.ts +1 -0
  487. package/dist/native/byte-index.d.ts.map +1 -1
  488. package/dist/native/byte-index.js +1 -1
  489. package/dist/native/byte-index.js.map +1 -1
  490. package/dist/native/contracts.d.ts +1 -0
  491. package/dist/native/contracts.d.ts.map +1 -1
  492. package/dist/native/native-backend-report.d.ts +2 -1
  493. package/dist/native/native-backend-report.d.ts.map +1 -1
  494. package/dist/native/native-backend-report.js +23 -0
  495. package/dist/native/native-backend-report.js.map +1 -1
  496. package/dist/native/tree-shape.d.ts +5 -7
  497. package/dist/native/tree-shape.d.ts.map +1 -1
  498. package/dist/native/tree-shape.js +11 -10
  499. package/dist/native/tree-shape.js.map +1 -1
  500. package/dist/presentation/bounds.d.ts +2 -0
  501. package/dist/presentation/bounds.d.ts.map +1 -1
  502. package/dist/presentation/bounds.js +8 -0
  503. package/dist/presentation/bounds.js.map +1 -1
  504. package/dist/review/candidates.d.ts.map +1 -1
  505. package/dist/review/candidates.js +4 -25
  506. package/dist/review/candidates.js.map +1 -1
  507. package/dist/review/deleted.js +1 -1
  508. package/dist/review/deleted.js.map +1 -1
  509. package/dist/review/report.d.ts.map +1 -1
  510. package/dist/review/report.js +4 -2
  511. package/dist/review/report.js.map +1 -1
  512. package/dist/review/summaries.d.ts.map +1 -1
  513. package/dist/review/summaries.js +14 -35
  514. package/dist/review/summaries.js.map +1 -1
  515. package/dist/review.d.ts +6 -0
  516. package/dist/review.d.ts.map +1 -1
  517. package/dist/review.js +5 -6
  518. package/dist/review.js.map +1 -1
  519. package/dist/scss/navigation.d.ts +13 -0
  520. package/dist/scss/navigation.d.ts.map +1 -0
  521. package/dist/scss/navigation.js +150 -0
  522. package/dist/scss/navigation.js.map +1 -0
  523. package/dist/scss/resolution.d.ts +190 -0
  524. package/dist/scss/resolution.d.ts.map +1 -0
  525. package/dist/scss/resolution.js +1802 -0
  526. package/dist/scss/resolution.js.map +1 -0
  527. package/dist/scss/syntax.d.ts +181 -0
  528. package/dist/scss/syntax.d.ts.map +1 -0
  529. package/dist/scss/syntax.js +1436 -0
  530. package/dist/scss/syntax.js.map +1 -0
  531. package/dist/sql/classify-sql-file.d.ts +7 -0
  532. package/dist/sql/classify-sql-file.d.ts.map +1 -1
  533. package/dist/sql/classify-sql-file.js +9 -0
  534. package/dist/sql/classify-sql-file.js.map +1 -1
  535. package/dist/sql/extract-facts.d.ts.map +1 -1
  536. package/dist/sql/extract-facts.js +517 -77
  537. package/dist/sql/extract-facts.js.map +1 -1
  538. package/dist/sql/lex.d.ts +100 -1
  539. package/dist/sql/lex.d.ts.map +1 -1
  540. package/dist/sql/lex.js +473 -11
  541. package/dist/sql/lex.js.map +1 -1
  542. package/dist/sql/lookup.d.ts +17 -0
  543. package/dist/sql/lookup.d.ts.map +1 -1
  544. package/dist/sql/lookup.js +21 -0
  545. package/dist/sql/lookup.js.map +1 -1
  546. package/dist/sql/navigation.d.ts +28 -1
  547. package/dist/sql/navigation.d.ts.map +1 -1
  548. package/dist/sql/navigation.js +474 -84
  549. package/dist/sql/navigation.js.map +1 -1
  550. package/dist/sql/object-mentions.d.ts +24 -0
  551. package/dist/sql/object-mentions.d.ts.map +1 -0
  552. package/dist/sql/object-mentions.js +233 -0
  553. package/dist/sql/object-mentions.js.map +1 -0
  554. package/dist/sql/review.d.ts +3 -0
  555. package/dist/sql/review.d.ts.map +1 -1
  556. package/dist/sql/review.js +15 -14
  557. package/dist/sql/review.js.map +1 -1
  558. package/dist/sql/routine-mentions.d.ts +61 -0
  559. package/dist/sql/routine-mentions.d.ts.map +1 -0
  560. package/dist/sql/routine-mentions.js +868 -0
  561. package/dist/sql/routine-mentions.js.map +1 -0
  562. package/dist/sql/source-graph.d.ts +18 -3
  563. package/dist/sql/source-graph.d.ts.map +1 -1
  564. package/dist/sql/source-graph.js +109 -32
  565. package/dist/sql/source-graph.js.map +1 -1
  566. package/dist/sqlite/raw-query-worker-pool.d.ts.map +1 -1
  567. package/dist/sqlite/raw-query-worker-pool.js +2 -0
  568. package/dist/sqlite/raw-query-worker-pool.js.map +1 -1
  569. package/dist/sqlite/types.d.ts +6 -5
  570. package/dist/sqlite/types.d.ts.map +1 -1
  571. package/dist/sqlite/write.d.ts.map +1 -1
  572. package/dist/sqlite/write.js.map +1 -1
  573. package/dist/sqlite-driver.d.ts +0 -1
  574. package/dist/sqlite-driver.d.ts.map +1 -1
  575. package/dist/sqlite-driver.js +0 -11
  576. package/dist/sqlite-driver.js.map +1 -1
  577. package/dist/terraform/navigation.d.ts.map +1 -1
  578. package/dist/terraform/navigation.js +1 -3
  579. package/dist/terraform/navigation.js.map +1 -1
  580. package/dist/terraform/syntax.d.ts.map +1 -1
  581. package/dist/terraform/syntax.js +1 -4
  582. package/dist/terraform/syntax.js.map +1 -1
  583. package/dist/types.d.ts +2 -0
  584. package/dist/types.d.ts.map +1 -1
  585. package/dist/util/ast.d.ts +5 -0
  586. package/dist/util/ast.d.ts.map +1 -1
  587. package/dist/util/ast.js +10 -0
  588. package/dist/util/ast.js.map +1 -1
  589. package/dist/util/atomic-file.d.ts +22 -0
  590. package/dist/util/atomic-file.d.ts.map +1 -0
  591. package/dist/util/atomic-file.js +106 -0
  592. package/dist/util/atomic-file.js.map +1 -0
  593. package/dist/util/collections.d.ts +5 -0
  594. package/dist/util/collections.d.ts.map +1 -1
  595. package/dist/util/collections.js +26 -0
  596. package/dist/util/collections.js.map +1 -1
  597. package/dist/util/concurrency.d.ts +8 -0
  598. package/dist/util/concurrency.d.ts.map +1 -1
  599. package/dist/util/concurrency.js +16 -0
  600. package/dist/util/concurrency.js.map +1 -1
  601. package/dist/util/confined-file.d.ts.map +1 -1
  602. package/dist/util/confined-file.js +1 -3
  603. package/dist/util/confined-file.js.map +1 -1
  604. package/dist/util/csharp-tree.d.ts +65 -0
  605. package/dist/util/csharp-tree.d.ts.map +1 -0
  606. package/dist/util/csharp-tree.js +266 -0
  607. package/dist/util/csharp-tree.js.map +1 -0
  608. package/dist/util/errors.d.ts +1 -0
  609. package/dist/util/errors.d.ts.map +1 -1
  610. package/dist/util/errors.js +3 -0
  611. package/dist/util/errors.js.map +1 -1
  612. package/dist/util/graph-edges.d.ts +2 -0
  613. package/dist/util/graph-edges.d.ts.map +1 -1
  614. package/dist/util/graph-edges.js +11 -0
  615. package/dist/util/graph-edges.js.map +1 -1
  616. package/dist/util/guards.d.ts +1 -0
  617. package/dist/util/guards.d.ts.map +1 -1
  618. package/dist/util/guards.js +6 -0
  619. package/dist/util/guards.js.map +1 -1
  620. package/dist/util/identifiers.d.ts +0 -24
  621. package/dist/util/identifiers.d.ts.map +1 -1
  622. package/dist/util/identifiers.js +0 -24
  623. package/dist/util/identifiers.js.map +1 -1
  624. package/dist/util/jvm-tree.d.ts +58 -0
  625. package/dist/util/jvm-tree.d.ts.map +1 -0
  626. package/dist/util/jvm-tree.js +153 -0
  627. package/dist/util/jvm-tree.js.map +1 -0
  628. package/dist/util/package-exports.d.ts +0 -22
  629. package/dist/util/package-exports.d.ts.map +1 -1
  630. package/dist/util/package-exports.js +25 -5
  631. package/dist/util/package-exports.js.map +1 -1
  632. package/dist/util/paths.d.ts +1 -0
  633. package/dist/util/paths.d.ts.map +1 -1
  634. package/dist/util/paths.js +10 -4
  635. package/dist/util/paths.js.map +1 -1
  636. package/dist/util/resolution/csharp.d.ts +20 -8
  637. package/dist/util/resolution/csharp.d.ts.map +1 -1
  638. package/dist/util/resolution/csharp.js +126 -127
  639. package/dist/util/resolution/csharp.js.map +1 -1
  640. package/dist/util/resolution/files.d.ts +6 -0
  641. package/dist/util/resolution/files.d.ts.map +1 -1
  642. package/dist/util/resolution/files.js +74 -21
  643. package/dist/util/resolution/files.js.map +1 -1
  644. package/dist/util/resolution/jvm.d.ts +21 -1
  645. package/dist/util/resolution/jvm.d.ts.map +1 -1
  646. package/dist/util/resolution/jvm.js +168 -100
  647. package/dist/util/resolution/jvm.js.map +1 -1
  648. package/dist/util/resolution/project-symbols.d.ts +1 -1
  649. package/dist/util/resolution/project-symbols.d.ts.map +1 -1
  650. package/dist/util/resolution/project-symbols.js.map +1 -1
  651. package/dist/util/resolution/specifier-targets.d.ts +4 -0
  652. package/dist/util/resolution/specifier-targets.d.ts.map +1 -1
  653. package/dist/util/resolution/specifier-targets.js +11 -3
  654. package/dist/util/resolution/specifier-targets.js.map +1 -1
  655. package/dist/util/resolution.d.ts.map +1 -1
  656. package/dist/util/resolution.js +21 -7
  657. package/dist/util/resolution.js.map +1 -1
  658. package/dist/util/syntax-tree.d.ts +16 -0
  659. package/dist/util/syntax-tree.d.ts.map +1 -0
  660. package/dist/util/syntax-tree.js +34 -0
  661. package/dist/util/syntax-tree.js.map +1 -0
  662. package/dist/util/text-scanning.d.ts +6 -0
  663. package/dist/util/text-scanning.d.ts.map +1 -0
  664. package/dist/util/text-scanning.js +35 -0
  665. package/dist/util/text-scanning.js.map +1 -0
  666. package/dist/util/trivia-tables.d.ts +13 -8
  667. package/dist/util/trivia-tables.d.ts.map +1 -1
  668. package/dist/util/trivia-tables.js +13 -72
  669. package/dist/util/trivia-tables.js.map +1 -1
  670. package/dist/util/trivia.d.ts +10 -3
  671. package/dist/util/trivia.d.ts.map +1 -1
  672. package/dist/util/trivia.js +209 -79
  673. package/dist/util/trivia.js.map +1 -1
  674. package/dist/util/windows-process-drain.d.ts.map +1 -1
  675. package/dist/util/windows-process-drain.js.map +1 -1
  676. package/dist/util/worker-threads.d.ts +16 -0
  677. package/dist/util/worker-threads.d.ts.map +1 -1
  678. package/dist/util/worker-threads.js +118 -0
  679. package/dist/util/worker-threads.js.map +1 -1
  680. package/dist/worker/native-worker-pool.d.ts.map +1 -1
  681. package/dist/worker/native-worker-pool.js +2 -1
  682. package/dist/worker/native-worker-pool.js.map +1 -1
  683. package/docs/mcp.md +82 -8
  684. package/package.json +7 -7
@@ -1,14 +1,14 @@
1
1
  import fsp from "node:fs/promises";
2
- import path from "node:path";
3
2
  import { createNavigationProvenance, okGoToResult } from "../indexer/navigation-provenance.js";
4
3
  import { buildIndexedCandidateCoverage } from "../indexer/navigation-references.js";
4
+ import { SymbolKind } from "../indexer/types.js";
5
5
  import { fileIdentityKey, normalizePath } from "../util/paths.js";
6
+ import { isSqlFilePath } from "./classify-sql-file.js";
6
7
  import { extractSqlFactsFromSource } from "./extract-facts.js";
7
- import { pushSqlLookupValue } from "./lookup.js";
8
- import { maskSqlStringsAndComments, normalizeSqlObjectName, SQL_IDENTIFIER_PART_PATTERN, splitTopLevelCommaSeparated, sqlObjectBaseNameLookupKey, sqlObjectLookupKey, sqlParenDepthAt, } from "./lex.js";
9
- function isSqlFile(filePath) {
10
- return path.extname(filePath).toLowerCase() === ".sql";
11
- }
8
+ import { addSqlDefinition, createSqlDefinitionIndex, sqlRoutineNameCandidates, } from "./lookup.js";
9
+ import { maskSqlQuotedIdentifiers, maskSqlStringsAndComments, normalizeSqlObjectName, SQL_IDENTIFIER_PART_PATTERN, splitTopLevelCommaSeparated, sqlObjectBaseNameLookupKey, sqlObjectLookupKey, sqlQueryScopes, sqlSourceClauses, } from "./lex.js";
10
+ import { sqlDefinedNameSpan, sqlObjectMentionCovers, sqlRelationReadSpans, sqlSpanCovers, sqlSyntacticObjectSpans, } from "./object-mentions.js";
11
+ import { findSqlRoutineMentions, findSqlRoutineSources, sqlRoutineDefinitionNamespace, sqlStatementDropsRoutine, } from "./routine-mentions.js";
12
12
  function rangeForToken(line, column, length) {
13
13
  return {
14
14
  start: { line, column },
@@ -18,7 +18,7 @@ function rangeForToken(line, column, length) {
18
18
  function sqlFiles(index) {
19
19
  return Array.from(index.byFile.values())
20
20
  .map((module) => normalizePath(module.file))
21
- .filter(isSqlFile)
21
+ .filter((file) => isSqlFilePath(file, index.languageExtensions))
22
22
  .sort((left, right) => left.localeCompare(right));
23
23
  }
24
24
  function getSqlNavigationCache(index) {
@@ -28,23 +28,23 @@ function getSqlNavigationCache(index) {
28
28
  };
29
29
  return index.sqlNavigation;
30
30
  }
31
+ /** Table, view, and index definitions. Routines resolve through `getSqlRoutineLookups`. */
31
32
  function getSqlDefinitionLookup(index) {
32
33
  const cache = getSqlNavigationCache(index);
33
34
  if (cache.definitionLookup)
34
35
  return cache.definitionLookup;
35
- const exact = new Map();
36
- const basename = new Map();
36
+ const lookup = createSqlDefinitionIndex();
37
37
  for (const file of sqlFiles(index)) {
38
38
  const module = index.byFile.get(fileIdentityKey(file));
39
39
  if (!module)
40
40
  continue;
41
41
  for (const local of module.locals) {
42
- pushSqlLookupValue(exact, sqlObjectLookupKey(local.localName), local);
43
- pushSqlLookupValue(basename, sqlObjectBaseNameLookupKey(local.localName), local);
42
+ if (local.kind !== SymbolKind.Routine)
43
+ addSqlDefinition(lookup, local.localName, local);
44
44
  }
45
45
  }
46
- cache.definitionLookup = { exact, basename };
47
- return cache.definitionLookup;
46
+ cache.definitionLookup = lookup;
47
+ return lookup;
48
48
  }
49
49
  function sqlDefinitionsFromLookup(lookup, objectName) {
50
50
  const normalizedName = sqlObjectLookupKey(objectName);
@@ -75,6 +75,7 @@ function sqlDefinitionMatches(lookup, objectName) {
75
75
  const SQL_IDENTIFIER = SQL_IDENTIFIER_PART_PATTERN;
76
76
  const SQL_DOTTED_TOKEN = String.raw `${SQL_IDENTIFIER}(?:\s*\.\s*${SQL_IDENTIFIER})*`;
77
77
  const SQL_DOTTED_TOKEN_RE = new RegExp(SQL_DOTTED_TOKEN, "g");
78
+ const SQL_IDENTIFIER_PART_RE = new RegExp(SQL_IDENTIFIER, "g");
78
79
  const SQL_SOURCE_KEYWORDS = new Set([
79
80
  "as",
80
81
  "on",
@@ -93,9 +94,8 @@ const SQL_SOURCE_KEYWORDS = new Set([
93
94
  "returning",
94
95
  ]);
95
96
  const SQL_SOURCE_MODIFIERS = new Set(["only", "lateral"]);
96
- const SQL_SOURCE_BOUNDARY_RE = /\b(?:where|group\s+by|order\s+by|having|limit|offset|returning|union|intersect|except|on|inner\s+join|left\s+join|right\s+join|full\s+join|cross\s+join|join)\b/i;
97
97
  function wordAtPosition(source, line, column) {
98
- const lineText = maskSqlStringsAndComments(source).split(/\r?\n/)[line - 1];
98
+ const lineText = maskSqlStringsAndComments(source, { escapeStrings: true }).split(/\r?\n/)[line - 1];
99
99
  if (!lineText)
100
100
  return null;
101
101
  const zeroBasedColumn = Math.max(0, column - 1);
@@ -113,14 +113,20 @@ function sqlObjectNameParts(name) {
113
113
  .map((part) => part.trim())
114
114
  .filter(Boolean);
115
115
  }
116
+ const slicesByFacts = new WeakMap();
117
+ /** The statements of one file's facts in source order. A file's facts are fixed, so the result is cached. */
116
118
  function sqlStatementSlices(facts) {
119
+ const cached = slicesByFacts.get(facts);
120
+ if (cached)
121
+ return cached;
117
122
  const slices = [];
118
123
  const seen = new Set();
119
124
  for (const fact of facts) {
120
- const key = `${fact.startLine}:${fact.endLine}:${fact.statementText}`;
121
- if (seen.has(key))
125
+ // One statement yields several facts. Its start offset tells it apart from an identical statement
126
+ // on the same line, which its lines and text cannot.
127
+ if (seen.has(fact.startIndex))
122
128
  continue;
123
- seen.add(key);
129
+ seen.add(fact.startIndex);
124
130
  slices.push({
125
131
  text: fact.statementText,
126
132
  startLine: fact.startLine,
@@ -128,15 +134,13 @@ function sqlStatementSlices(facts) {
128
134
  endLine: fact.endLine,
129
135
  });
130
136
  }
131
- return slices.sort((left, right) => left.startLine - right.startLine || left.endLine - right.endLine);
137
+ slices.sort((left, right) => left.startLine - right.startLine || left.endLine - right.endLine);
138
+ slicesByFacts.set(facts, slices);
139
+ return slices;
132
140
  }
133
141
  function sqlStatementAtLine(facts, line) {
134
142
  return (sqlStatementSlices(facts).find((statement) => line >= statement.startLine && line <= statement.endLine) ?? null);
135
143
  }
136
- function sourceClauseEndIndex(text, start) {
137
- const boundary = text.slice(start).search(SQL_SOURCE_BOUNDARY_RE);
138
- return boundary < 0 ? text.length : start + boundary;
139
- }
140
144
  function cteNamesForStatement(text) {
141
145
  const cteNames = new Set();
142
146
  const cteRe = new RegExp(String.raw `(?:\bwith\s+(?:recursive\s+)?|,\s*)(${SQL_IDENTIFIER})(?:\s*\([^)]*\))?\s+as\s*\(`, "gi");
@@ -150,12 +154,14 @@ function cteNamesForStatement(text) {
150
154
  return cteNames;
151
155
  }
152
156
  function parseSqlSourceEntry(entry) {
157
+ const leading = entry.length - entry.trimStart().length;
153
158
  const trimmed = entry.trim();
154
159
  if (!trimmed || trimmed.startsWith("("))
155
160
  return null;
156
161
  const tokenRe = new RegExp(SQL_DOTTED_TOKEN, "gy");
157
162
  let cursor = 0;
158
163
  let objectName = null;
164
+ let objectOffset = -1;
159
165
  while (cursor < trimmed.length) {
160
166
  tokenRe.lastIndex = cursor;
161
167
  const match = tokenRe.exec(trimmed);
@@ -167,12 +173,13 @@ function parseSqlSourceEntry(entry) {
167
173
  cursor = match.index + match[0].length;
168
174
  if (!SQL_SOURCE_MODIFIERS.has(normalized.toLowerCase())) {
169
175
  objectName = normalized;
176
+ objectOffset = leading + match.index;
170
177
  break;
171
178
  }
172
179
  while (cursor < trimmed.length && /\s/.test(trimmed[cursor] ?? ""))
173
180
  cursor += 1;
174
181
  }
175
- if (!objectName)
182
+ if (!objectName || objectOffset < 0)
176
183
  return null;
177
184
  let rest = trimmed.slice(cursor).trimStart();
178
185
  if (rest.startsWith("."))
@@ -182,31 +189,9 @@ function parseSqlSourceEntry(entry) {
182
189
  const aliasMatch = new RegExp(String.raw `^(${SQL_IDENTIFIER})`, "i").exec(rest);
183
190
  const aliasName = normalizeSqlObjectName(aliasMatch?.[1]) ?? null;
184
191
  if (!aliasName || SQL_SOURCE_KEYWORDS.has(aliasName.toLowerCase())) {
185
- return { objectName, aliasName: null };
186
- }
187
- return { objectName, aliasName };
188
- }
189
- function sqlAliasMapForStatement(statementText) {
190
- const aliases = new Map();
191
- const cteNames = cteNamesForStatement(statementText);
192
- const clauseRe = /\b(?:from|using|join|inner\s+join|left\s+join|right\s+join|full\s+join|cross\s+join)\s+/gi;
193
- for (const match of statementText.matchAll(clauseRe)) {
194
- if (sqlParenDepthAt(statementText, match.index ?? 0) > 0)
195
- continue;
196
- const start = (match.index ?? 0) + match[0].length;
197
- const clause = statementText.slice(start, sourceClauseEndIndex(statementText, start));
198
- for (const part of splitTopLevelCommaSeparated(clause)) {
199
- const parsed = parseSqlSourceEntry(part);
200
- if (!parsed?.aliasName)
201
- continue;
202
- const objectKey = sqlObjectLookupKey(parsed.objectName);
203
- const objectBaseKey = sqlObjectBaseNameLookupKey(parsed.objectName);
204
- if (cteNames.has(objectKey) || cteNames.has(objectBaseKey))
205
- continue;
206
- aliases.set(sqlObjectLookupKey(parsed.aliasName), parsed.objectName);
207
- }
192
+ return { objectName, aliasName: null, objectOffset };
208
193
  }
209
- return aliases;
194
+ return { objectName, aliasName, objectOffset };
210
195
  }
211
196
  function unambiguousSqlPrefixDefinitionName(lookup, objectName) {
212
197
  const matches = sqlDefinitionMatches(lookup, objectName);
@@ -218,23 +203,116 @@ function unambiguousSqlPrefixDefinitionName(lookup, objectName) {
218
203
  return matches.basename[0]?.localName ?? null;
219
204
  return null;
220
205
  }
221
- function resolveQualifiedSqlName(lookup, name, statementText) {
222
- if (sqlDefinitionsFromLookup(lookup, name).length)
223
- return name;
206
+ /** Resolve a qualifier against the nearest query's relation aliases and indexed routine sources. */
207
+ function sqlSourceBindings(lookups, statementText) {
208
+ const masked = maskSqlStringsAndComments(statementText, { escapeStrings: true });
209
+ const scan = maskSqlQuotedIdentifiers(masked);
210
+ const scopes = sqlQueryScopes(scan);
211
+ const bindings = new Map();
212
+ const addBinding = (offset, key, binding) => {
213
+ const scope = scopes.at(offset);
214
+ let inScope = bindings.get(scope);
215
+ if (!inScope) {
216
+ inScope = new Map();
217
+ bindings.set(scope, inScope);
218
+ }
219
+ const previous = inScope.get(key);
220
+ if (!previous) {
221
+ inScope.set(key, binding);
222
+ }
223
+ else if (previous.kind !== binding.kind ||
224
+ (previous.kind === "relation" && binding.kind === "relation" && previous.objectName !== binding.objectName)) {
225
+ inScope.set(key, { kind: "ambiguous" });
226
+ }
227
+ };
228
+ const cteNames = cteNamesForStatement(masked);
229
+ const routineSources = lookups.namespaceByDefinition.size
230
+ ? findSqlRoutineSources(statementText).filter(({ mention }) => routineCandidates(lookups, mention).length > 0)
231
+ : [];
232
+ for (const source of sqlSourceClauses(scan)) {
233
+ const clause = masked.slice(source.end, source.clauseEnd);
234
+ let nextPartStart = source.end;
235
+ for (const part of splitTopLevelCommaSeparated(clause)) {
236
+ const partStart = masked.indexOf(part, nextPartStart);
237
+ if (partStart < 0)
238
+ continue;
239
+ const partEnd = partStart + part.length;
240
+ nextPartStart = partEnd + 1;
241
+ const parsed = parseSqlSourceEntry(part);
242
+ if (!parsed)
243
+ continue;
244
+ // A routine source owns only its own source item. A later call that merely falls inside this
245
+ // slice, such as the next statement of a procedure body, must not drop the relation binding.
246
+ if (routineSources.some(({ mention }) => mention.start === partStart + parsed.objectOffset))
247
+ continue;
248
+ const objectKey = sqlObjectLookupKey(parsed.objectName);
249
+ const objectBaseKey = sqlObjectBaseNameLookupKey(parsed.objectName);
250
+ if (cteNames.has(objectKey) || cteNames.has(objectBaseKey))
251
+ continue;
252
+ const relation = { kind: "relation", objectName: parsed.objectName };
253
+ if (parsed.aliasName) {
254
+ addBinding(source.start, sqlObjectLookupKey(parsed.aliasName), relation);
255
+ }
256
+ else {
257
+ addBinding(source.start, objectKey, relation);
258
+ if (objectBaseKey !== objectKey)
259
+ addBinding(source.start, objectBaseKey, relation);
260
+ }
261
+ }
262
+ }
263
+ for (const { mention, alias } of routineSources) {
264
+ if (alias) {
265
+ addBinding(mention.start, sqlObjectLookupKey(alias), { kind: "routine" });
266
+ }
267
+ else {
268
+ addBinding(mention.start, sqlObjectLookupKey(mention.name), { kind: "routine" });
269
+ addBinding(mention.start, sqlObjectBaseNameLookupKey(mention.name), { kind: "routine" });
270
+ }
271
+ }
272
+ return {
273
+ at(offset, parts) {
274
+ for (let scope = scopes.at(offset);; scope = scopes.parent.get(scope) ?? 0) {
275
+ const inScope = bindings.get(scope);
276
+ let binding = inScope?.get(sqlObjectLookupKey(parts[0] ?? ""));
277
+ for (let count = 2; count < parts.length; count += 1) {
278
+ const candidate = inScope?.get(sqlObjectLookupKey(parts.slice(0, count).join(".")));
279
+ if (candidate && binding && candidate !== binding)
280
+ return { kind: "ambiguous" };
281
+ binding ??= candidate;
282
+ }
283
+ if (binding)
284
+ return binding;
285
+ if (!scope)
286
+ break;
287
+ }
288
+ return null;
289
+ },
290
+ };
291
+ }
292
+ function resolveQualifiedSqlName(lookup, routineLookups, name, statementText, offset) {
224
293
  const parts = sqlObjectNameParts(name);
225
294
  if (parts.length < 2)
226
295
  return name;
227
296
  const firstPart = parts[0];
228
297
  if (!firstPart)
229
298
  return null;
230
- if (statementText) {
231
- const maskedStatementText = maskSqlStringsAndComments(statementText);
299
+ if (statementText && offset !== undefined) {
300
+ const maskedStatementText = maskSqlStringsAndComments(statementText, { escapeStrings: true });
232
301
  if (cteNamesForStatement(maskedStatementText).has(sqlObjectLookupKey(firstPart)))
233
302
  return null;
234
- const aliasTarget = sqlAliasMapForStatement(maskedStatementText).get(sqlObjectLookupKey(firstPart));
235
- if (aliasTarget && sqlDefinitionsFromLookup(lookup, aliasTarget).length)
236
- return aliasTarget;
303
+ if (sqlObjectMentionCovers(statementText, offset)) {
304
+ const direct = sqlDefinitionMatches(lookup, name);
305
+ return direct.exact.length || direct.basename.length === 1 ? name : null;
306
+ }
307
+ const binding = sqlSourceBindings(routineLookups, statementText).at(offset, parts);
308
+ if (binding) {
309
+ if (binding.kind !== "relation")
310
+ return null;
311
+ return sqlDefinitionsFromLookup(lookup, binding.objectName).length ? binding.objectName : null;
312
+ }
237
313
  }
314
+ if (sqlDefinitionsFromLookup(lookup, name).length)
315
+ return name;
238
316
  for (let partCount = parts.length - 1; partCount >= 1; partCount -= 1) {
239
317
  const candidate = parts.slice(0, partCount).join(".");
240
318
  const resolvedName = unambiguousSqlPrefixDefinitionName(lookup, candidate);
@@ -261,7 +339,15 @@ function sqlNameResolvesToDefinition(lookup, name, definition) {
261
339
  return matches.exact.includes(definition);
262
340
  return matches.basename.length === 1 && matches.basename[0] === definition;
263
341
  }
264
- function factReferenceRanges(fact, objectName) {
342
+ /**
343
+ * Where the last `partCount` parts of a dotted name begin. Rename edits the definition's own name and
344
+ * keeps the qualifier in front of it: a rename of `f` edits the `f` in `public.f`.
345
+ */
346
+ function trailingPartsOffset(dottedName, partCount) {
347
+ const parts = [...dottedName.matchAll(SQL_IDENTIFIER_PART_RE)];
348
+ return parts[parts.length - partCount]?.index ?? 0;
349
+ }
350
+ function factReferenceRanges(fact, objectName, claimedStarts, keepParts = 0) {
265
351
  const statement = {
266
352
  text: fact.statementText,
267
353
  startLine: fact.startLine,
@@ -270,22 +356,35 @@ function factReferenceRanges(fact, objectName) {
270
356
  };
271
357
  const objectKey = sqlObjectLookupKey(objectName);
272
358
  const ranges = [];
273
- const maskedStatementText = maskSqlStringsAndComments(statement.text);
359
+ const sourceSpans = fact.kind === "reads_from" || fact.kind === "joins" ? sqlRelationReadSpans(statement.text) : null;
360
+ const maskedStatementText = maskSqlStringsAndComments(statement.text, { escapeStrings: true });
274
361
  for (const match of maskedStatementText.matchAll(SQL_DOTTED_TOKEN_RE)) {
275
362
  const token = normalizeSqlObjectName(match[0]);
276
363
  if (!token || sqlObjectLookupKey(token) !== objectKey)
277
364
  continue;
278
365
  const offset = match.index ?? 0;
279
- ranges.push(rangeForToken(statementLineForOffset(statement, offset), statementColumnForOffset(statement, offset), match[0].length));
366
+ if (claimedStarts?.has(offset))
367
+ continue;
368
+ if (sourceSpans &&
369
+ !sourceSpans.some((span) => span.start === offset && sqlObjectLookupKey(span.name) === objectKey))
370
+ continue;
371
+ const nameOffset = keepParts ? trailingPartsOffset(match[0], keepParts) : 0;
372
+ ranges.push(rangeForToken(statementLineForOffset(statement, offset + nameOffset), statementColumnForOffset(statement, offset + nameOffset), match[0].length - nameOffset));
280
373
  }
281
374
  return ranges;
282
375
  }
283
- function qualifiedReferenceRanges(lookup, statement, definition) {
376
+ function qualifiedReferenceRanges(lookup, routineLookups, statement, definition, claimedStarts, keepParts = 0) {
284
377
  const ranges = [];
285
- const maskedStatementText = maskSqlStringsAndComments(statement.text);
286
- const aliases = sqlAliasMapForStatement(maskedStatementText);
378
+ let ambiguous = false;
379
+ const maskedStatementText = maskSqlStringsAndComments(statement.text, { escapeStrings: true });
380
+ const bindings = sqlSourceBindings(routineLookups, statement.text);
287
381
  const cteNames = cteNamesForStatement(maskedStatementText);
382
+ // One scan for the statement. A fresh scan for every qualified name is quadratic.
383
+ const objectSpans = sqlSyntacticObjectSpans(statement.text);
288
384
  for (const match of maskedStatementText.matchAll(SQL_DOTTED_TOKEN_RE)) {
385
+ const offset = match.index ?? 0;
386
+ if (claimedStarts?.has(offset))
387
+ continue;
289
388
  const token = normalizeSqlObjectName(match[0]);
290
389
  if (!token)
291
390
  continue;
@@ -297,19 +396,38 @@ function qualifiedReferenceRanges(lookup, statement, definition) {
297
396
  continue;
298
397
  if (cteNames.has(sqlObjectLookupKey(firstPart)))
299
398
  continue;
300
- const aliasTarget = aliases.get(sqlObjectLookupKey(firstPart));
301
- const matchesAlias = aliasTarget ? sqlNameResolvesToDefinition(lookup, aliasTarget, definition) : false;
302
- let matchesPrefix = false;
303
- for (let partCount = parts.length - 1; partCount >= 1 && !matchesPrefix; partCount -= 1) {
304
- const candidate = parts.slice(0, partCount).join(".");
305
- matchesPrefix = sqlNameResolvesToDefinition(lookup, candidate, definition);
399
+ if (sqlSpanCovers(objectSpans, offset)) {
400
+ const direct = sqlDefinitionMatches(lookup, token);
401
+ if (!direct.exact.length && direct.basename.length > 1 && direct.basename.includes(definition))
402
+ ambiguous = true;
403
+ if (sqlNameResolvesToDefinition(lookup, token, definition)) {
404
+ const nameOffset = keepParts ? trailingPartsOffset(match[0], keepParts) : 0;
405
+ ranges.push(rangeForToken(statementLineForOffset(statement, offset + nameOffset), statementColumnForOffset(statement, offset + nameOffset), match[0].length - nameOffset));
406
+ }
407
+ continue;
306
408
  }
307
- if (!matchesAlias && !matchesPrefix)
409
+ const binding = bindings.at(offset, parts);
410
+ if (binding?.kind === "ambiguous") {
411
+ ambiguous = true;
412
+ continue;
413
+ }
414
+ if (binding?.kind === "routine")
415
+ continue;
416
+ let matches = false;
417
+ if (binding) {
418
+ matches = sqlNameResolvesToDefinition(lookup, binding.objectName, definition);
419
+ }
420
+ else {
421
+ for (let partCount = parts.length - 1; partCount >= 1 && !matches; partCount -= 1) {
422
+ const candidate = parts.slice(0, partCount).join(".");
423
+ matches = sqlNameResolvesToDefinition(lookup, candidate, definition);
424
+ }
425
+ }
426
+ if (!matches)
308
427
  continue;
309
- const offset = match.index ?? 0;
310
428
  ranges.push(rangeForToken(statementLineForOffset(statement, offset), statementColumnForOffset(statement, offset), match[0].length));
311
429
  }
312
- return ranges;
430
+ return { ranges, ambiguous };
313
431
  }
314
432
  async function sourceForFile(filePath, index) {
315
433
  const cache = getSqlNavigationCache(index);
@@ -332,17 +450,185 @@ async function sqlFactsForFile(index, filePath) {
332
450
  cache.factsByFile.set(key, facts);
333
451
  return facts;
334
452
  }
453
+ const routineLookupsByIndex = new WeakMap();
454
+ const mentionsByFacts = new WeakMap();
455
+ function siteKey(file, line, column) {
456
+ return `${fileIdentityKey(file)}:${line}:${column}`;
457
+ }
458
+ /** The name space of each routine one file defines, by the position where its statement starts. */
459
+ async function routineNamespacesByStart(index, file) {
460
+ const namespaces = new Map();
461
+ for (const fact of await sqlFactsForFile(index, file)) {
462
+ if (fact.kind !== "defines_routine")
463
+ continue;
464
+ namespaces.set(`${fact.startLine}:${fact.startColumn}`, sqlRoutineDefinitionNamespace(fact.statementText));
465
+ }
466
+ return namespaces;
467
+ }
468
+ async function buildSqlRoutineLookups(index) {
469
+ const lookups = {
470
+ callable: createSqlDefinitionIndex(),
471
+ trigger: createSqlDefinitionIndex(),
472
+ namespaceByDefinition: new Map(),
473
+ definitionByStart: new Map(),
474
+ };
475
+ for (const file of sqlFiles(index)) {
476
+ const locals = index.byFile.get(fileIdentityKey(file))?.locals ?? [];
477
+ const routines = locals.filter((local) => local.kind === SymbolKind.Routine);
478
+ if (!routines.length)
479
+ continue;
480
+ const namespaces = await routineNamespacesByStart(index, file);
481
+ for (const routine of routines) {
482
+ const { line, column } = routine.range.start;
483
+ const namespace = namespaces.get(`${line}:${column}`) ?? "callable";
484
+ addSqlDefinition(lookups[namespace], routine.localName, routine);
485
+ lookups.namespaceByDefinition.set(routine, namespace);
486
+ lookups.definitionByStart.set(siteKey(file, line, column), routine);
487
+ }
488
+ }
489
+ return lookups;
490
+ }
491
+ function getSqlRoutineLookups(index) {
492
+ const cached = routineLookupsByIndex.get(index);
493
+ if (cached)
494
+ return cached;
495
+ const lookups = buildSqlRoutineLookups(index);
496
+ routineLookupsByIndex.set(index, lookups);
497
+ // A failed build must not stay cached; the next lookup tries again.
498
+ lookups.catch(() => routineLookupsByIndex.delete(index));
499
+ return lookups;
500
+ }
501
+ /**
502
+ * The mentions in each statement that name a routine. A keyword mention always does. A bare `name(`
503
+ * does only when an indexed routine has that name, because `INSERT INTO users (id)` has the same shape.
504
+ */
505
+ function statementMentions(lookups, facts) {
506
+ const cached = mentionsByFacts.get(facts);
507
+ if (cached)
508
+ return cached;
509
+ const statements = [];
510
+ for (const statement of sqlStatementSlices(facts)) {
511
+ const mentions = findSqlRoutineMentions(statement.text).filter((mention) => !mention.speculative || routineCandidates(lookups, mention).length);
512
+ if (mentions.length)
513
+ statements.push({ statement, mentions });
514
+ }
515
+ mentionsByFacts.set(facts, statements);
516
+ return statements;
517
+ }
518
+ function routineCandidates(lookups, mention) {
519
+ return sqlRoutineNameCandidates(lookups[mention.namespace], mention.name, (definition) => definition.localName)
520
+ .candidates;
521
+ }
522
+ /**
523
+ * Start offsets of the tokens in each statement that name a routine, by statement start. A table or
524
+ * view reference skips these tokens: a name in a routine position is not a relation.
525
+ */
526
+ function claimedMentionStarts(lookups, facts) {
527
+ const claimed = new Map();
528
+ for (const { statement, mentions } of statementMentions(lookups, facts)) {
529
+ claimed.set(`${statement.startLine}:${statement.startColumn}`, new Set(mentions.map((mention) => mention.start)));
530
+ }
531
+ return claimed;
532
+ }
533
+ function mentionRange(statement, mention, keepParts = 0) {
534
+ const start = mention.start + (keepParts ? trailingPartsOffset(statement.text.slice(mention.start, mention.end), keepParts) : 0);
535
+ return {
536
+ start: {
537
+ line: statementLineForOffset(statement, start),
538
+ column: statementColumnForOffset(statement, start),
539
+ },
540
+ end: {
541
+ line: statementLineForOffset(statement, mention.end),
542
+ column: statementColumnForOffset(statement, mention.end),
543
+ },
544
+ };
545
+ }
546
+ function statementOffsetAtPosition(statement, line, column) {
547
+ if (line < statement.startLine || line > statement.endLine)
548
+ return undefined;
549
+ let lineStart = 0;
550
+ for (let current = statement.startLine; current < line; current += 1) {
551
+ const newline = statement.text.indexOf("\n", lineStart);
552
+ if (newline < 0)
553
+ return undefined;
554
+ lineStart = newline + 1;
555
+ }
556
+ return lineStart + column - (line === statement.startLine ? statement.startColumn : 1);
557
+ }
558
+ function goToRoutineMention(index, lookups, file, facts, position) {
559
+ for (const statement of sqlStatementSlices(facts)) {
560
+ const offset = statementOffsetAtPosition(statement, position.line, position.column);
561
+ // Several statements can share one line, so only the statement that holds the position counts.
562
+ if (offset === undefined || offset < 0 || offset >= statement.text.length)
563
+ continue;
564
+ const mention = findSqlRoutineMentions(statement.text).find((entry) => offset >= entry.start && offset < entry.end);
565
+ if (!mention)
566
+ return null;
567
+ if (mention.kind === "definition") {
568
+ const definition = lookups.definitionByStart.get(siteKey(file, statement.startLine, statement.startColumn));
569
+ return definition ? okGoToResult(index, definition, { resolution: "exact", confidence: "high" }) : null;
570
+ }
571
+ const candidates = routineCandidates(lookups, mention);
572
+ const [only] = candidates;
573
+ if (only && candidates.length === 1)
574
+ return okGoToResult(index, only, { resolution: "exact", confidence: "high" });
575
+ if (candidates.length)
576
+ return { status: "not_found", reason: "Several SQL routines share this name" };
577
+ // A bare `name(` can name a table or an index; a keyword such as `CALL` or `DROP FUNCTION` names a routine.
578
+ return mention.speculative ? null : { status: "not_found", reason: "No matching SQL routine definition" };
579
+ }
580
+ return null;
581
+ }
582
+ function routineMentionIsProven(lookups, statementText, offset) {
583
+ const mention = findSqlRoutineMentions(statementText).find((entry) => offset >= entry.start && offset < entry.end);
584
+ if (!mention)
585
+ return false;
586
+ // A bare `name(` is a routine only when an indexed routine has that name. Otherwise it may be a table.
587
+ if (!mention.speculative)
588
+ return true;
589
+ return routineCandidates(lookups, mention).length > 0;
590
+ }
591
+ /**
592
+ * True when the position names an object or a routine by SQL syntax: a `FROM`/`JOIN`/`CALL`/`ON`
593
+ * target, not a column that happens to share a table's name. The name that a `CREATE` statement
594
+ * defines is no mention: it names the definition itself.
595
+ */
596
+ export async function sqlPositionIsProvenObjectOrRoutineMention(index, req) {
597
+ if (!isSqlFilePath(req.file, index.languageExtensions))
598
+ return false;
599
+ const facts = await sqlFactsForFile(index, req.file);
600
+ const routineLookups = await getSqlRoutineLookups(index);
601
+ for (const statement of sqlStatementSlices(facts)) {
602
+ const offset = statementOffsetAtPosition(statement, req.line, req.column);
603
+ if (offset === undefined || offset < 0 || offset >= statement.text.length)
604
+ continue;
605
+ const defined = sqlDefinedNameSpan(statement.text);
606
+ if (defined && offset >= defined.start && offset < defined.end)
607
+ return false;
608
+ if (routineMentionIsProven(routineLookups, statement.text, offset))
609
+ return true;
610
+ return sqlObjectMentionCovers(statement.text, offset);
611
+ }
612
+ return false;
613
+ }
335
614
  export async function goToSqlDefinition(index, req) {
336
- if (!isSqlFile(req.file))
615
+ if (!isSqlFilePath(req.file, index.languageExtensions))
337
616
  return null;
338
617
  const source = await sourceForFile(req.file, index);
339
- const name = wordAtPosition(source, req.line, req.column);
340
- if (!name)
341
- return { status: "not_found", reason: "No SQL object at position" };
342
618
  const lookup = getSqlDefinitionLookup(index);
619
+ const routineLookups = await getSqlRoutineLookups(index);
343
620
  const facts = await sqlFactsForFile(index, req.file);
621
+ // `DROP FUNCTION f`, `CALL f`, and the like name a routine even when the project defines none, so they
622
+ // never fall through to a table of the same name.
623
+ const routineResult = goToRoutineMention(index, routineLookups, req.file, facts, req);
624
+ if (routineResult)
625
+ return routineResult;
344
626
  const statement = sqlStatementAtLine(facts, req.line);
345
- const resolvedName = resolveQualifiedSqlName(lookup, name, statement?.text ?? null);
627
+ const name = wordAtPosition(source, req.line, req.column);
628
+ if (!name)
629
+ return { status: "not_found", reason: "No SQL object at position" };
630
+ const offset = statement ? statementOffsetAtPosition(statement, req.line, req.column) : undefined;
631
+ const resolvedName = resolveQualifiedSqlName(lookup, routineLookups, name, statement?.text ?? null, offset);
346
632
  if (!resolvedName)
347
633
  return { status: "not_found", reason: "No matching SQL object definition" };
348
634
  const definitions = sqlDefinitionsFromLookup(lookup, resolvedName);
@@ -354,24 +640,65 @@ export async function goToSqlDefinition(index, req) {
354
640
  confidence: "high",
355
641
  });
356
642
  }
357
- export async function findSqlReferences(index, definition, options) {
358
- if (!isSqlFile(definition.file))
643
+ /**
644
+ * The site of the name `definition` declares, as in `users` in `CREATE TABLE users`. A definition spans
645
+ * its whole statement, so its range does not say where its name is.
646
+ */
647
+ async function declarationSiteKey(index, definition) {
648
+ const { line, column } = definition.range.start;
649
+ const facts = await sqlFactsForFile(index, definition.file);
650
+ const statement = sqlStatementSlices(facts).find((slice) => slice.startLine === line && slice.startColumn === column);
651
+ const name = statement ? sqlDefinedNameSpan(statement.text) : null;
652
+ if (!statement || !name)
653
+ return null;
654
+ const nameLine = statementLineForOffset(statement, name.start);
655
+ return siteKey(definition.file, nameLine, statementColumnForOffset(statement, name.start));
656
+ }
657
+ /**
658
+ * The indexed definition declared at the site `definition` names. Impact analysis passes a copy of a
659
+ * definition, and a lookup by object identity cannot match a copy.
660
+ */
661
+ function indexedSqlDefinition(index, definition) {
662
+ const { line, column } = definition.range.start;
663
+ const locals = index.byFile.get(fileIdentityKey(definition.file))?.locals ?? [];
664
+ return (locals.find((local) => local.range.start.line === line &&
665
+ local.range.start.column === column &&
666
+ local.kind === definition.kind &&
667
+ local.localName === definition.localName) ?? null);
668
+ }
669
+ export async function findSqlReferences(index, requested, options) {
670
+ if (!isSqlFilePath(requested.file, index.languageExtensions))
359
671
  return null;
672
+ const definition = indexedSqlDefinition(index, requested);
673
+ // Without the indexed definition no lookup can match, and an empty list would claim a complete scan.
674
+ if (!definition)
675
+ return { status: "not_found", reason: "SQL definition is not in the index" };
360
676
  const references = [];
361
677
  const seen = new Set();
362
678
  const lookup = getSqlDefinitionLookup(index);
679
+ const routineLookups = await getSqlRoutineLookups(index);
680
+ const routineNamespace = routineLookups.namespaceByDefinition.get(definition);
681
+ const hasRoutines = !!routineLookups.namespaceByDefinition.size;
363
682
  const candidateFiles = sqlFiles(index);
364
683
  const scannedFiles = [];
684
+ // Files with a mention that several routine definitions could own, so no one definition owns it.
685
+ const ambiguousFiles = [];
365
686
  const includeDefinition = options?.includeDefinition ?? true;
687
+ const keepParts = options?.renameRanges ? sqlObjectNameParts(definition.localName).length : 0;
366
688
  const maxReferences = typeof options?.maxReferences === "number" && options.maxReferences > 0 ? options.maxReferences : undefined;
367
689
  const collectionLimit = maxReferences === undefined ? undefined : maxReferences + 1;
368
- const definitionKey = `${fileIdentityKey(definition.file)}:${definition.range.start.line}:${definition.range.start.column}`;
690
+ const definitionKey = siteKey(definition.file, definition.range.start.line, definition.range.start.column);
691
+ // A usage lookup leaves out the declaration. A routine's declaration is a mention, skipped below.
692
+ // A relation's is not, so find the site of its name here.
693
+ let declarationKey = null;
694
+ if (!includeDefinition && !routineNamespace)
695
+ declarationKey = await declarationSiteKey(index, definition);
369
696
  const hasReachedCollectionLimit = () => collectionLimit !== undefined && references.length >= collectionLimit;
370
697
  const addReference = (file, range) => {
371
698
  if (hasReachedCollectionLimit())
372
699
  return;
373
- const key = `${fileIdentityKey(file)}:${range.start.line}:${range.start.column}`;
374
- if (!includeDefinition && key === definitionKey)
700
+ const key = siteKey(file, range.start.line, range.start.column);
701
+ if (key === declarationKey)
375
702
  return;
376
703
  if (seen.has(key))
377
704
  return;
@@ -383,13 +710,44 @@ export async function findSqlReferences(index, definition, options) {
383
710
  break;
384
711
  scannedFiles.push(file);
385
712
  const facts = await sqlFactsForFile(index, file);
713
+ if (routineNamespace) {
714
+ for (const { statement, mentions } of statementMentions(routineLookups, facts)) {
715
+ for (const mention of mentions) {
716
+ if (hasReachedCollectionLimit())
717
+ break;
718
+ if (mention.namespace !== routineNamespace)
719
+ continue;
720
+ if (mention.kind === "definition") {
721
+ // A definition always names itself, even when several definitions share the name. Only a
722
+ // lookup that includes the declaration reports it.
723
+ const namesDefinition = siteKey(file, statement.startLine, statement.startColumn) === definitionKey;
724
+ if (includeDefinition && namesDefinition)
725
+ addReference(file, mentionRange(statement, mention, keepParts));
726
+ continue;
727
+ }
728
+ const candidates = routineCandidates(routineLookups, mention);
729
+ if (!candidates.includes(definition))
730
+ continue;
731
+ if (candidates.length === 1)
732
+ addReference(file, mentionRange(statement, mention, keepParts));
733
+ else if (!ambiguousFiles.includes(file))
734
+ ambiguousFiles.push(file);
735
+ }
736
+ }
737
+ continue;
738
+ }
739
+ const claimedStarts = hasRoutines ? claimedMentionStarts(routineLookups, facts) : undefined;
386
740
  for (const fact of facts) {
387
741
  if (hasReachedCollectionLimit())
388
742
  break;
743
+ // The name in `DROP FUNCTION name` is a routine mention, never a table of the same name.
744
+ if (fact.kind === "drops_object" && sqlStatementDropsRoutine(fact.statementText))
745
+ continue;
746
+ const claimed = claimedStarts?.get(`${fact.startLine}:${fact.startColumn}`);
389
747
  for (const name of [fact.objectName, fact.relatedObjectName]) {
390
748
  if (!name || !sqlNameResolvesToDefinition(lookup, name, definition))
391
749
  continue;
392
- for (const range of factReferenceRanges(fact, name)) {
750
+ for (const range of factReferenceRanges(fact, name, claimed, keepParts)) {
393
751
  addReference(file, range);
394
752
  }
395
753
  }
@@ -399,9 +757,14 @@ export async function findSqlReferences(index, definition, options) {
399
757
  for (const statement of sqlStatementSlices(facts)) {
400
758
  if (hasReachedCollectionLimit())
401
759
  break;
402
- for (const range of qualifiedReferenceRanges(lookup, statement, definition)) {
760
+ if (sqlStatementDropsRoutine(statement.text))
761
+ continue;
762
+ const claimed = claimedStarts?.get(`${statement.startLine}:${statement.startColumn}`);
763
+ const { ranges, ambiguous } = qualifiedReferenceRanges(lookup, routineLookups, statement, definition, claimed, keepParts);
764
+ for (const range of ranges)
403
765
  addReference(file, range);
404
- }
766
+ if (ambiguous && !ambiguousFiles.includes(file))
767
+ ambiguousFiles.push(file);
405
768
  }
406
769
  }
407
770
  references.sort((left, right) => {
@@ -426,7 +789,34 @@ export async function findSqlReferences(index, definition, options) {
426
789
  candidateFiles,
427
790
  scannedFiles,
428
791
  truncated,
792
+ strategyUnavailableFiles: ambiguousFiles,
429
793
  }),
430
794
  };
431
795
  }
796
+ /**
797
+ * What each changed SQL symbol is called in graph edges: a table, view, or index by its name, a
798
+ * routine by its name and name space. The index stores no name space, and an index restored from a
799
+ * cache never read the statement, so the name space comes from the facts of the changed file.
800
+ */
801
+ export async function sqlChangedSymbolTargets(index, symbols) {
802
+ const targets = new Map();
803
+ const namespacesByFile = new Map();
804
+ for (const symbol of symbols) {
805
+ if (symbol.kind === SymbolKind.Table || symbol.kind === SymbolKind.View || symbol.kind === SymbolKind.Index) {
806
+ targets.set(symbol, { name: symbol.name, namespace: "relation" });
807
+ continue;
808
+ }
809
+ if (symbol.kind !== SymbolKind.Routine)
810
+ continue;
811
+ const fileKey = fileIdentityKey(symbol.file);
812
+ let namespaces = namespacesByFile.get(fileKey);
813
+ if (!namespaces) {
814
+ namespaces = await routineNamespacesByStart(index, symbol.file);
815
+ namespacesByFile.set(fileKey, namespaces);
816
+ }
817
+ const { line, column } = symbol.range.start;
818
+ targets.set(symbol, { name: symbol.name, namespace: namespaces.get(`${line}:${column}`) ?? "callable" });
819
+ }
820
+ return targets;
821
+ }
432
822
  //# sourceMappingURL=navigation.js.map