@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
@@ -0,0 +1,868 @@
1
+ import { createSqlObjectNameRegExp, isBareSqlKeyword, maskSqlQuotedIdentifiers, maskSqlStringsAndComments, normalizeSqlObjectName, SQL_OBJECT_NAME_PATTERN, splitTopLevelCommaSeparated, sqlParenDepthAt, sqlMatchingParen as matchingParen, sqlSourceClauses, } from "./lex.js";
2
+ import { skipWhitespace } from "../util/text-scanning.js";
3
+ /** The statement head that defines a routine. Fact extraction and mention scanning share it. */
4
+ export const SQL_ROUTINE_DEFINITION_RE = /\bcreate\s+(?:or\s+replace\s+)?(function|procedure|trigger)\s+/i;
5
+ const DROP_ROUTINE_RE = /^\s*drop\s+(?:function|procedure|trigger)\b/i;
6
+ const CODE_STATEMENT_RE = /^\s*(?:create\s+(?:or\s+replace\s+)?(?:function|procedure)|do)\b/i;
7
+ const DO_STATEMENT_RE = /^\s*do\b/i;
8
+ const LANGUAGE_KEYWORD_RE = /\blanguage\b/gi;
9
+ // The name a `LANGUAGE` clause gives: a bare word, a double-quoted identifier, or a string.
10
+ const LANGUAGE_NAME_RE = /^(?:'([A-Za-z_]\w*)'|"([A-Za-z_]\w*)"|([A-Za-z_]\w*))/;
11
+ const ROUTINE_KEYWORD_RE = /\b(function|procedure|routine|trigger)\b/gi;
12
+ const IF_EXISTS_RE = /if\s+exists\s+/iy;
13
+ const NAME_RE = createSqlObjectNameRegExp("y");
14
+ // A name must not continue a longer word, a dotted name, a variable, or a `::` cast.
15
+ const NAME_BOUNDARY = String.raw `(?<![\w$@#:.])`;
16
+ const CALL_KEYWORD_RE = new RegExp(String.raw `${NAME_BOUNDARY}(call|exec(?:ute)?)\s+(?:@[A-Za-z_]\w*\s*=\s*)?(${SQL_OBJECT_NAME_PATTERN})`, "gi");
17
+ const CREATE_TABLE_COLUMNS_RE = new RegExp(String.raw `\bcreate\s+table\s+(?:if\s+not\s+exists\s+)?${SQL_OBJECT_NAME_PATTERN}\s*\(`, "gi");
18
+ const CALL_SHAPE_RE = new RegExp(String.raw `${NAME_BOUNDARY}(${SQL_OBJECT_NAME_PATTERN})\s*\(`, "g");
19
+ // `AS (`, `AS MATERIALIZED (`, and `AS NOT MATERIALIZED (` open the body of a common table expression.
20
+ const CTE_BODY_RE = /^\s*as(?:\s+(?:not\s+)?materialized)?\s*\(/i;
21
+ const WORD_RE = /[A-Za-z_][\w$]*/y;
22
+ const WITH_ORDINALITY_RE = /with\s+ordinality\b/iy;
23
+ // A table hint is a word with an optional argument: `NOLOCK`, `INDEX (ix_users)`, `INDEX = 0`.
24
+ const TABLE_HINT_RE = /^(\w+)\s*(?:[(=][\s\S]*)?$/;
25
+ // `INSERT` and its MySQL sibling `REPLACE`, which can put modifiers before the table.
26
+ const INSERT_RE = /\b(?:insert|replace)\b/gi;
27
+ // The scanner reads PostgreSQL and SQL Server text: arrays, escape strings, and nested block comments.
28
+ const MASK_OPTIONS = { arrayBrackets: true, nestedBlockComments: true, escapeStrings: true };
29
+ // The body language of a function, procedure, or `DO` block that Codegraph reads as SQL.
30
+ const BODY_LANGUAGES = { sql: true, plpgsql: true };
31
+ // Words before a name that is followed by `(` but is a table, index, type, or routine definition,
32
+ // not a call: `INSERT INTO users (id)`, `INSERT users (id)`, `COPY users (id)`, `REFERENCES users (id)`.
33
+ const NON_CALL_PRECEDING_WORDS = {
34
+ table: true,
35
+ view: true,
36
+ into: true,
37
+ references: true,
38
+ index: true,
39
+ type: true,
40
+ sequence: true,
41
+ schema: true,
42
+ only: true,
43
+ as: true,
44
+ exists: true,
45
+ function: true,
46
+ procedure: true,
47
+ routine: true,
48
+ trigger: true,
49
+ call: true,
50
+ exec: true,
51
+ execute: true,
52
+ insert: true,
53
+ copy: true,
54
+ };
55
+ // Words after `EXEC`, `EXECUTE`, or `CALL` that do not name a routine: `EXECUTE AS`, `GRANT EXECUTE ON`.
56
+ const NON_ROUTINE_NAME_WORDS = {
57
+ as: true,
58
+ on: true,
59
+ to: true,
60
+ with: true,
61
+ from: true,
62
+ where: true,
63
+ into: true,
64
+ set: true,
65
+ order: true,
66
+ group: true,
67
+ limit: true,
68
+ using: true,
69
+ select: true,
70
+ values: true,
71
+ function: true,
72
+ procedure: true,
73
+ };
74
+ // Words before `FUNCTION`, `PROCEDURE`, `ROUTINE`, or `TRIGGER` in a statement about an existing routine.
75
+ const REFERENCE_PRECEDING_WORDS = { alter: true, on: true, enable: true, disable: true };
76
+ // A bare `CALL (`, `EXEC (`, or `EXECUTE (` is the keyword, not a routine of that name.
77
+ const CALL_KEYWORDS = { call: true, exec: true, execute: true };
78
+ // A PL/pgSQL `EXECUTE` runs the command string that an expression gives, so its operand is no routine.
79
+ const EXECUTE_WORDS = { exec: true, execute: true };
80
+ // MySQL modifiers between `INSERT` and the table: `INSERT IGNORE users (id)`. T-SQL adds `TOP (n)`.
81
+ const INSERT_MODIFIERS = { ignore: true, low_priority: true, delayed: true, high_priority: true };
82
+ // Words that follow a source in a `FROM` list without naming its alias.
83
+ const NON_ALIAS_WORDS = {
84
+ on: true,
85
+ using: true,
86
+ where: true,
87
+ group: true,
88
+ order: true,
89
+ having: true,
90
+ limit: true,
91
+ offset: true,
92
+ fetch: true,
93
+ for: true,
94
+ returning: true,
95
+ union: true,
96
+ intersect: true,
97
+ except: true,
98
+ window: true,
99
+ with: true,
100
+ join: true,
101
+ inner: true,
102
+ left: true,
103
+ right: true,
104
+ full: true,
105
+ cross: true,
106
+ natural: true,
107
+ outer: true,
108
+ apply: true,
109
+ lateral: true,
110
+ tablesample: true,
111
+ into: true,
112
+ option: true,
113
+ set: true,
114
+ values: true,
115
+ select: true,
116
+ from: true,
117
+ };
118
+ // T-SQL table hints, which `FROM users (NOLOCK)` puts in parentheses without `WITH`.
119
+ const TABLE_HINTS = {
120
+ forcescan: true,
121
+ forceseek: true,
122
+ holdlock: true,
123
+ index: true,
124
+ nolock: true,
125
+ noexpand: true,
126
+ nowait: true,
127
+ paglock: true,
128
+ readcommitted: true,
129
+ readcommittedlock: true,
130
+ readpast: true,
131
+ readuncommitted: true,
132
+ repeatableread: true,
133
+ rowlock: true,
134
+ serializable: true,
135
+ snapshot: true,
136
+ spatial_window_max_cells: true,
137
+ tablock: true,
138
+ tablockx: true,
139
+ updlock: true,
140
+ xlock: true,
141
+ };
142
+ const SOURCE_MODIFIERS = { lateral: true, only: true };
143
+ function hasWord(table, word) {
144
+ return Object.hasOwn(table, word);
145
+ }
146
+ function previousWord(text, index) {
147
+ let end = index;
148
+ while (end > 0 && /\s/.test(text[end - 1] ?? ""))
149
+ end -= 1;
150
+ let start = end;
151
+ while (start > 0 && /[A-Za-z0-9_$]/.test(text[start - 1] ?? ""))
152
+ start -= 1;
153
+ return start < end ? text.slice(start, end).toLowerCase() : undefined;
154
+ }
155
+ /** A preceding word that is syntax, rather than part of a variable or dotted name. */
156
+ function previousBareSqlWord(scan, index) {
157
+ let end = index;
158
+ while (end > 0 && /\s/.test(scan[end - 1] ?? ""))
159
+ end -= 1;
160
+ let start = end;
161
+ while (start > 0 && /[A-Za-z0-9_$]/.test(scan[start - 1] ?? ""))
162
+ start -= 1;
163
+ if (start === end || !isBareSqlKeyword(scan, start, end))
164
+ return undefined;
165
+ return scan.slice(start, end).toLowerCase();
166
+ }
167
+ function nameAt(text, index) {
168
+ const start = skipWhitespace(text, index);
169
+ NAME_RE.lastIndex = start;
170
+ const match = NAME_RE.exec(text);
171
+ if (!match)
172
+ return null;
173
+ const name = normalizeSqlObjectName(match[0]);
174
+ return name ? { name, start, end: start + match[0].length } : null;
175
+ }
176
+ /** Where the block comment that opens at `start` ends. A block comment can hold block comments. */
177
+ function blockCommentEnd(text, start) {
178
+ let depth = 0;
179
+ let cursor = start;
180
+ while (cursor < text.length) {
181
+ if (text.startsWith("/*", cursor)) {
182
+ depth += 1;
183
+ cursor += 2;
184
+ }
185
+ else if (text.startsWith("*/", cursor)) {
186
+ depth -= 1;
187
+ cursor += 2;
188
+ if (!depth)
189
+ return cursor;
190
+ }
191
+ else {
192
+ cursor += 1;
193
+ }
194
+ }
195
+ return text.length;
196
+ }
197
+ /**
198
+ * Skips whitespace and comments, which can sit between two tokens: between `LANGUAGE` and the language
199
+ * name, or between `SELECT` and a column.
200
+ */
201
+ function skipTrivia(text, index) {
202
+ let cursor = skipWhitespace(text, index);
203
+ while (text.startsWith("--", cursor) || text.startsWith("/*", cursor)) {
204
+ if (text.startsWith("--", cursor)) {
205
+ const lineEnd = text.indexOf("\n", cursor);
206
+ cursor = lineEnd < 0 ? text.length : lineEnd;
207
+ }
208
+ else {
209
+ cursor = blockCommentEnd(text, cursor);
210
+ }
211
+ cursor = skipWhitespace(text, cursor);
212
+ }
213
+ return cursor;
214
+ }
215
+ /**
216
+ * True unless the statement declares a body language that Codegraph cannot read as SQL. The last
217
+ * `LANGUAGE` clause outside the parentheses wins: an earlier `language` can be a parameter name, as in
218
+ * `f(language text)`. A clause whose name cannot be read counts as another language, so its body
219
+ * stays masked.
220
+ */
221
+ function bodyLanguageIsReadable(statementText, scan) {
222
+ const clauses = [...scan.matchAll(LANGUAGE_KEYWORD_RE)].filter((match) => !sqlParenDepthAt(scan, match.index ?? 0));
223
+ const clause = clauses.at(-1);
224
+ if (!clause)
225
+ return true;
226
+ const nameStart = skipTrivia(statementText, (clause.index ?? 0) + clause[0].length);
227
+ const named = LANGUAGE_NAME_RE.exec(statementText.slice(nameStart));
228
+ const language = named?.[1] ?? named?.[2] ?? named?.[3];
229
+ return !!language && hasWord(BODY_LANGUAGES, language.toLowerCase());
230
+ }
231
+ /** The `AS '...'` body of a CREATE FUNCTION or CREATE PROCEDURE. A default or any other string is not. */
232
+ function routineSingleQuotedBody() {
233
+ return (before) => {
234
+ const code = maskSqlQuotedIdentifiers(before);
235
+ return previousWord(code, code.length) === "as" && !sqlParenDepthAt(code, code.length);
236
+ };
237
+ }
238
+ /** Decides which dollar-quoted block holds the routine body: the one after `AS`, or the first of a `DO` statement. */
239
+ function routineBodyBlock(scan) {
240
+ if (DO_STATEMENT_RE.test(scan)) {
241
+ let seen = false;
242
+ return () => {
243
+ const first = !seen;
244
+ seen = true;
245
+ return first;
246
+ };
247
+ }
248
+ return (before) => {
249
+ const code = maskSqlQuotedIdentifiers(before);
250
+ return previousWord(code, code.length) === "as" && !sqlParenDepthAt(code, code.length);
251
+ };
252
+ }
253
+ /**
254
+ * Masks strings and comments. The `$$` body of a function, procedure, or `DO` block, and the
255
+ * single-quoted `AS '...'` body of a function or procedure, stay visible when the language is SQL,
256
+ * PL/pgSQL, or omitted. Any other string stays masked: a parameter default, a setting, an ordinary
257
+ * literal, or the body of a language Codegraph cannot read. `inBody` is true when a body stays visible.
258
+ */
259
+ function maskStatementCode(statementText) {
260
+ const masked = maskSqlStringsAndComments(statementText, MASK_OPTIONS);
261
+ if (!CODE_STATEMENT_RE.test(masked))
262
+ return { masked, inBody: false };
263
+ const scan = maskSqlQuotedIdentifiers(masked);
264
+ if (!bodyLanguageIsReadable(statementText, scan))
265
+ return { masked, inBody: false };
266
+ const keepDollar = statementText.includes("$");
267
+ const keepSingle = statementText.includes("'");
268
+ if (!keepDollar && !keepSingle)
269
+ return { masked, inBody: false };
270
+ const withBody = maskSqlStringsAndComments(statementText, {
271
+ ...MASK_OPTIONS,
272
+ ...(keepDollar ? { keepDollarQuotedBody: routineBodyBlock(scan) } : {}),
273
+ ...(keepSingle ? { keepSingleQuotedBody: routineSingleQuotedBody() } : {}),
274
+ });
275
+ return { masked: withBody, inBody: withBody !== masked };
276
+ }
277
+ function keywordMentionKind(keyword, previous, isDefinition) {
278
+ if (isDefinition)
279
+ return "definition";
280
+ if (previous === "exec" || previous === "execute")
281
+ return keyword === "function" || keyword === "procedure" ? "call" : null;
282
+ if (previous === "drop")
283
+ return "drop";
284
+ return previous && hasWord(REFERENCE_PRECEDING_WORDS, previous) ? "reference" : null;
285
+ }
286
+ /**
287
+ * A `DROP` or `GRANT ... ON` statement can name several routines, as in `DROP FUNCTION f(integer), g`.
288
+ * Each name after a comma is a mention of the same kind and name space. A parenthesized signature
289
+ * between two names is skipped, and the list ends at the first token that is no comma.
290
+ */
291
+ function collectTargetList(masked, scan, firstEnd, target, mentions) {
292
+ let cursor = skipWhitespace(scan, firstEnd);
293
+ for (;;) {
294
+ if (scan[cursor] === "(") {
295
+ const close = matchingParen(scan, cursor);
296
+ if (close < 0)
297
+ return;
298
+ cursor = skipWhitespace(scan, close + 1);
299
+ }
300
+ if (scan[cursor] !== ",")
301
+ return;
302
+ const named = nameAt(masked, cursor + 1);
303
+ if (!named)
304
+ return;
305
+ mentions.set(named.start, { ...named, ...target, speculative: false });
306
+ cursor = skipWhitespace(scan, named.end);
307
+ }
308
+ }
309
+ function collectKeywordMentions(masked, scan, mentions) {
310
+ const definition = SQL_ROUTINE_DEFINITION_RE.exec(scan);
311
+ const definitionKeyword = definition?.[1];
312
+ const definitionKeywordStart = definition && definitionKeyword ? definition.index + definition[0].lastIndexOf(definitionKeyword) : -1;
313
+ for (const match of scan.matchAll(ROUTINE_KEYWORD_RE)) {
314
+ const keywordStart = match.index ?? 0;
315
+ const keyword = (match[1] ?? "").toLowerCase();
316
+ const previous = previousWord(scan, keywordStart);
317
+ const kind = keywordMentionKind(keyword, previous, keywordStart === definitionKeywordStart);
318
+ if (!kind)
319
+ continue;
320
+ let nameFrom = keywordStart + match[0].length;
321
+ if (kind === "drop" || kind === "reference") {
322
+ IF_EXISTS_RE.lastIndex = skipWhitespace(scan, nameFrom);
323
+ if (IF_EXISTS_RE.exec(scan))
324
+ nameFrom = IF_EXISTS_RE.lastIndex;
325
+ }
326
+ const named = nameAt(masked, nameFrom);
327
+ if (!named)
328
+ continue;
329
+ const namespace = keyword === "trigger" ? "trigger" : "callable";
330
+ mentions.set(named.start, { ...named, kind, namespace, speculative: false });
331
+ // `ALTER` and `ENABLE` take one name, and a comma after it separates actions, as in
332
+ // `DISABLE TRIGGER a, ENABLE TRIGGER b`. `DROP` and `GRANT ... ON` take a list.
333
+ if (kind === "drop" || previous === "on")
334
+ collectTargetList(masked, scan, named.end, { kind, namespace }, mentions);
335
+ }
336
+ }
337
+ /**
338
+ * Comments are blank in `masked`, so a comment between `CALL`/`EXEC` and the name fails a literal
339
+ * compare. Accept that gap when every changed character is a comment. A string is blank too, but it
340
+ * is not a comment, so `CALL 'note' norm` stays rejected.
341
+ */
342
+ function callKeywordMatchAllowsComments(statement, maskedMatch, start) {
343
+ if (statement.startsWith(maskedMatch, start))
344
+ return true;
345
+ if (start < 0 || start + maskedMatch.length > statement.length)
346
+ return false;
347
+ let depth = 0;
348
+ let line = false;
349
+ let index = 0;
350
+ while (index < maskedMatch.length) {
351
+ const original = statement[start + index] ?? "";
352
+ const masked = maskedMatch[index] ?? "";
353
+ const nextOriginal = statement[start + index + 1] ?? "";
354
+ if (!depth && !line && original === "-" && nextOriginal === "-")
355
+ line = true;
356
+ // A block comment can hold block comments.
357
+ if (!line && original === "/" && nextOriginal === "*")
358
+ depth += 1;
359
+ const inComment = depth > 0 || line;
360
+ if (original !== masked && (!inComment || (masked !== " " && masked !== "\n")))
361
+ return false;
362
+ if (line && original === "\n")
363
+ line = false;
364
+ if (depth && original === "*" && nextOriginal === "/") {
365
+ const maskedSlash = maskedMatch[index + 1] ?? "";
366
+ if (maskedSlash !== " " && maskedSlash !== "\n" && maskedSlash !== "/")
367
+ return false;
368
+ depth -= 1;
369
+ index += 2;
370
+ continue;
371
+ }
372
+ index += 1;
373
+ }
374
+ return true;
375
+ }
376
+ function wordAt(text, index) {
377
+ WORD_RE.lastIndex = index;
378
+ return WORD_RE.exec(text)?.[0].toLowerCase() ?? "";
379
+ }
380
+ /** True when a parenthesized list holds nothing but T-SQL table hints, so it is no argument list. */
381
+ function isTableHintList(content) {
382
+ return splitTopLevelCommaSeparated(content).every((part) => {
383
+ const hint = TABLE_HINT_RE.exec(part.trim())?.[1];
384
+ return !!hint && hasWord(TABLE_HINTS, hint.toLowerCase());
385
+ });
386
+ }
387
+ /** A table hint can take an argument: `INDEX (ix_orders)` is a hint, not a call of `INDEX`. */
388
+ function excludeHintCallShapes(scan, open, close, excluded) {
389
+ for (const match of scan.slice(open + 1, close).matchAll(CALL_SHAPE_RE)) {
390
+ excluded.add(open + 1 + (match.index ?? 0));
391
+ }
392
+ }
393
+ /**
394
+ * Reads one source of a `FROM` list, `JOIN`, or `APPLY`: a name, a function call, or a parenthesized
395
+ * query, then an optional alias with a column list. A parenthesis after the alias opens its column
396
+ * list, and one after a name that holds only table hints opens those hints. Neither is a call; the
397
+ * source's own arguments are. Any other parenthesis after the name makes the source a call of that
398
+ * routine, which `calls` collects. Returns where the source ends, or -1 when no source starts at `from`.
399
+ */
400
+ function excludeSourceItem(scan, from, excluded, calls) {
401
+ let cursor = skipWhitespace(scan, from);
402
+ for (let word = wordAt(scan, cursor); hasWord(SOURCE_MODIFIERS, word); word = wordAt(scan, cursor)) {
403
+ cursor = skipWhitespace(scan, cursor + word.length);
404
+ }
405
+ let called = null;
406
+ if (scan[cursor] === "(") {
407
+ const close = matchingParen(scan, cursor);
408
+ if (close < 0)
409
+ return -1;
410
+ cursor = close + 1;
411
+ }
412
+ else {
413
+ const source = nameAt(scan, cursor);
414
+ if (!source)
415
+ return -1;
416
+ cursor = skipWhitespace(scan, source.end);
417
+ if (scan[cursor] === "(") {
418
+ const close = matchingParen(scan, cursor);
419
+ if (close < 0)
420
+ return -1;
421
+ if (isTableHintList(scan.slice(cursor + 1, close))) {
422
+ excluded.add(source.start);
423
+ excludeHintCallShapes(scan, cursor, close, excluded);
424
+ }
425
+ else {
426
+ called = source;
427
+ }
428
+ cursor = close + 1;
429
+ }
430
+ }
431
+ cursor = skipWhitespace(scan, cursor);
432
+ WITH_ORDINALITY_RE.lastIndex = cursor;
433
+ if (WITH_ORDINALITY_RE.test(scan))
434
+ cursor = skipWhitespace(scan, WITH_ORDINALITY_RE.lastIndex);
435
+ if (wordAt(scan, cursor) === "as")
436
+ cursor = skipWhitespace(scan, cursor + 2);
437
+ const named = nameAt(scan, cursor);
438
+ const alias = named && !hasWord(NON_ALIAS_WORDS, named.name.toLowerCase()) ? named : null;
439
+ if (called)
440
+ calls?.push({ start: called.start, end: called.end, aliasStart: alias?.start ?? null });
441
+ if (alias) {
442
+ cursor = skipWhitespace(scan, alias.end);
443
+ if (scan[cursor] === "(") {
444
+ // `FROM generate_series(1, 3) g(i)`: the parenthesis opens the alias's column list.
445
+ excluded.add(alias.start);
446
+ const close = matchingParen(scan, cursor);
447
+ if (close < 0)
448
+ return -1;
449
+ cursor = skipWhitespace(scan, close + 1);
450
+ }
451
+ }
452
+ // `FROM users u WITH (NOLOCK)` puts table hints after `WITH`.
453
+ const hintsOpen = skipWhitespace(scan, cursor + 4);
454
+ if (wordAt(scan, cursor) === "with" && scan[hintsOpen] === "(") {
455
+ excluded.add(cursor);
456
+ const close = matchingParen(scan, hintsOpen);
457
+ if (close < 0)
458
+ return -1;
459
+ if (isTableHintList(scan.slice(hintsOpen + 1, close)))
460
+ excludeHintCallShapes(scan, hintsOpen, close, excluded);
461
+ return close + 1;
462
+ }
463
+ return cursor;
464
+ }
465
+ const JOIN_INTRO_WORDS = {
466
+ inner: true,
467
+ left: true,
468
+ right: true,
469
+ full: true,
470
+ cross: true,
471
+ natural: true,
472
+ outer: true,
473
+ };
474
+ // Words that end a join predicate and the surrounding FROM list: `ON a.id = b.id WHERE ...`.
475
+ const ON_END_WORDS = {
476
+ where: true,
477
+ group: true,
478
+ order: true,
479
+ having: true,
480
+ limit: true,
481
+ offset: true,
482
+ fetch: true,
483
+ returning: true,
484
+ union: true,
485
+ intersect: true,
486
+ except: true,
487
+ window: true,
488
+ };
489
+ function joinIntroCanPrecede(word, ahead) {
490
+ if (ahead === "join" || ahead === "apply")
491
+ return true;
492
+ if (ahead === "outer")
493
+ return word === "left" || word === "right" || word === "full" || word === "natural";
494
+ if (word !== "natural")
495
+ return false;
496
+ return ahead === "left" || ahead === "right" || ahead === "full" || ahead === "inner" || ahead === "cross";
497
+ }
498
+ /** The `JOIN` or `APPLY` keyword at `index`, including `LEFT OUTER JOIN` and `CROSS APPLY`. */
499
+ function joinKeywordAt(scan, index) {
500
+ let cursor = skipWhitespace(scan, index);
501
+ for (;;) {
502
+ const word = wordAt(scan, cursor);
503
+ if (word === "join" || word === "apply")
504
+ return { at: cursor, end: cursor + word.length };
505
+ const ahead = wordAt(scan, skipWhitespace(scan, cursor + word.length));
506
+ if (!hasWord(JOIN_INTRO_WORDS, word) || !joinIntroCanPrecede(word, ahead))
507
+ return null;
508
+ cursor = skipWhitespace(scan, cursor + word.length);
509
+ }
510
+ }
511
+ /** Where the `ON` expression ends: a comma, a semicolon, a `)`, or the next clause or join. */
512
+ function skipOnExpression(scan, index) {
513
+ let depth = 0;
514
+ let cursor = index;
515
+ while (cursor < scan.length) {
516
+ const char = scan[cursor] ?? "";
517
+ if (char === "(") {
518
+ depth += 1;
519
+ cursor += 1;
520
+ continue;
521
+ }
522
+ if (char === ")") {
523
+ if (depth === 0)
524
+ return cursor;
525
+ depth -= 1;
526
+ cursor += 1;
527
+ continue;
528
+ }
529
+ if (depth === 0 && (char === "," || char === ";"))
530
+ return cursor;
531
+ if (depth !== 0 || !/[A-Za-z_]/.test(char)) {
532
+ cursor += 1;
533
+ continue;
534
+ }
535
+ const word = wordAt(scan, cursor);
536
+ if (!word) {
537
+ cursor += 1;
538
+ continue;
539
+ }
540
+ if (hasWord(ON_END_WORDS, word) || joinKeywordAt(scan, cursor))
541
+ return cursor;
542
+ cursor += word.length;
543
+ }
544
+ return cursor;
545
+ }
546
+ function skipJoinPredicate(scan, index) {
547
+ const cursor = skipWhitespace(scan, index);
548
+ const word = wordAt(scan, cursor);
549
+ if (word === "on")
550
+ return skipOnExpression(scan, cursor + word.length);
551
+ if (word !== "using")
552
+ return cursor;
553
+ const open = skipWhitespace(scan, cursor + word.length);
554
+ if (scan[open] !== "(")
555
+ return cursor;
556
+ const close = matchingParen(scan, open);
557
+ return close < 0 ? scan.length : close + 1;
558
+ }
559
+ /**
560
+ * Consumes `[type] JOIN source [ON expr | USING (...)]` chains that follow one source. Each join
561
+ * keyword is recorded so its own source clause is not read again. Returns where the chain ends,
562
+ * which is a comma when another source follows the predicate.
563
+ */
564
+ function consumeJoinChain(scan, index, excluded, calls, consumedJoins) {
565
+ let cursor = index;
566
+ for (;;) {
567
+ const keyword = joinKeywordAt(scan, cursor);
568
+ if (!keyword)
569
+ return cursor;
570
+ const next = excludeSourceItem(scan, keyword.end, excluded, calls);
571
+ if (next < 0 || next <= keyword.end)
572
+ return cursor;
573
+ consumedJoins.add(keyword.at);
574
+ cursor = skipJoinPredicate(scan, next);
575
+ }
576
+ }
577
+ function collectSourceItemExclusions(scan, excluded, calls) {
578
+ const consumedJoins = new Set();
579
+ for (const source of sqlSourceClauses(scan)) {
580
+ if (consumedJoins.has(source.start))
581
+ continue;
582
+ let cursor = source.end;
583
+ const takesList = source.kind === "from" || source.kind === "using";
584
+ for (;;) {
585
+ if (!takesList && cursor >= source.clauseEnd)
586
+ break;
587
+ const next = excludeSourceItem(scan, cursor, excluded, calls);
588
+ if (next < 0 || next <= cursor)
589
+ break;
590
+ cursor = consumeJoinChain(scan, next, excluded, calls, consumedJoins);
591
+ if (!takesList)
592
+ break;
593
+ // `FROM a JOIN b ON a.id = b.id, generate_series(1, 3) norm(i)`: the comma is past the join
594
+ // keyword that ended the recorded FROM slice, and `norm(i)` is the next source's column list.
595
+ const after = skipWhitespace(scan, cursor);
596
+ if (after >= scan.length || scan[after] !== ",")
597
+ break;
598
+ cursor = after + 1;
599
+ }
600
+ }
601
+ }
602
+ /**
603
+ * Skips the modifiers after `INSERT`: `IGNORE` and `LOW_PRIORITY` in MySQL, `TOP (n) [PERCENT]` in
604
+ * T-SQL. `TOP (n)` is no call, so it is excluded here. Returns -1 when its parenthesis is unbalanced.
605
+ */
606
+ function skipInsertModifiers(scan, from, excluded) {
607
+ let cursor = skipWhitespace(scan, from);
608
+ for (;;) {
609
+ const word = wordAt(scan, cursor);
610
+ const next = skipWhitespace(scan, cursor + word.length);
611
+ if (hasWord(INSERT_MODIFIERS, word)) {
612
+ cursor = next;
613
+ }
614
+ else if (word === "top" && scan[next] === "(") {
615
+ const close = matchingParen(scan, next);
616
+ if (close < 0)
617
+ return -1;
618
+ excluded.add(cursor);
619
+ cursor = skipWhitespace(scan, close + 1);
620
+ if (wordAt(scan, cursor) === "percent")
621
+ cursor = skipWhitespace(scan, cursor + "percent".length);
622
+ }
623
+ else {
624
+ return cursor;
625
+ }
626
+ }
627
+ }
628
+ /** `INSERT IGNORE users (id)` and `INSERT TOP (1) dbo.users (id)` name a table, not a routine. */
629
+ function excludeInsertTargets(scan, excluded) {
630
+ for (const keyword of scan.matchAll(INSERT_RE)) {
631
+ let cursor = skipInsertModifiers(scan, (keyword.index ?? 0) + keyword[0].length, excluded);
632
+ if (cursor < 0)
633
+ continue;
634
+ if (wordAt(scan, cursor) === "into")
635
+ cursor = skipWhitespace(scan, cursor + "into".length);
636
+ const target = nameAt(scan, cursor);
637
+ if (target && scan[skipWhitespace(scan, target.end)] === "(")
638
+ excluded.add(target.start);
639
+ }
640
+ }
641
+ /** Column types are not calls; the expression after a top-level computed-column AS is. */
642
+ function collectCreateTableColumnShapes(scan, excluded, computed) {
643
+ for (const match of scan.matchAll(CREATE_TABLE_COLUMNS_RE)) {
644
+ const create = match.index ?? 0;
645
+ if (!isBareSqlKeyword(scan, create, create + 6))
646
+ continue;
647
+ const open = create + match[0].length - 1;
648
+ const close = matchingParen(scan, open);
649
+ if (close < 0)
650
+ continue;
651
+ let columnStart = open + 1;
652
+ let depth = 0;
653
+ for (let cursor = columnStart; cursor <= close; cursor += 1) {
654
+ const char = scan[cursor];
655
+ if (char === "(")
656
+ depth += 1;
657
+ if (char === ")" && cursor !== close)
658
+ depth -= 1;
659
+ if ((char !== "," || depth) && cursor !== close)
660
+ continue;
661
+ const column = nameAt(scan, columnStart);
662
+ if (column && column.end < cursor) {
663
+ const next = skipWhitespace(scan, column.end);
664
+ if (wordAt(scan, next) === "as" && isBareSqlKeyword(scan, next, next + 2)) {
665
+ const expression = nameAt(scan, next + 2);
666
+ if (expression &&
667
+ expression.name.toLowerCase() !== "cast" &&
668
+ expression.start < cursor &&
669
+ scan[skipWhitespace(scan, expression.end)] === "(") {
670
+ computed.add(expression.start);
671
+ }
672
+ }
673
+ else {
674
+ const type = nameAt(scan, next);
675
+ if (type && type.start < cursor && scan[skipWhitespace(scan, type.end)] === "(")
676
+ excluded.add(type.start);
677
+ }
678
+ }
679
+ columnStart = cursor + 1;
680
+ }
681
+ }
682
+ }
683
+ /**
684
+ * Call shapes that are no calls. Index, CTE, source alias, and INSERT target parentheses name
685
+ * non-routines; CREATE TABLE column types do too, unlike computed-column expressions.
686
+ */
687
+ function excludedCallShapeStarts(scan, computed) {
688
+ const excluded = new Set();
689
+ if (/^\s*create\s+(?:unique\s+)?index\b/i.test(scan)) {
690
+ const onRe = /\bon\s+/gi;
691
+ for (const match of scan.matchAll(onRe)) {
692
+ const keywordAt = match.index ?? 0;
693
+ if (sqlParenDepthAt(scan, keywordAt) > 0)
694
+ continue;
695
+ let cursor = keywordAt + match[0].length;
696
+ let named = nameAt(scan, cursor);
697
+ while (named && (named.name.toLowerCase() === "only" || named.name.toLowerCase() === "lateral")) {
698
+ cursor = named.end;
699
+ named = nameAt(scan, cursor);
700
+ }
701
+ if (!named || scan[skipWhitespace(scan, named.end)] !== "(")
702
+ continue;
703
+ excluded.add(named.start);
704
+ break;
705
+ }
706
+ }
707
+ const cteRe = new RegExp(String.raw `(?:\bwith\s+(?:recursive\s+)?|,\s*)(${SQL_OBJECT_NAME_PATTERN})\s*\(`, "gi");
708
+ for (const match of scan.matchAll(cteRe)) {
709
+ const rawName = match[1] ?? "";
710
+ if (!rawName)
711
+ continue;
712
+ const matchStart = match.index ?? 0;
713
+ const parenIndex = matchStart + match[0].length - 1;
714
+ let nameEnd = parenIndex;
715
+ while (nameEnd > matchStart && /\s/.test(scan[nameEnd - 1] ?? ""))
716
+ nameEnd -= 1;
717
+ const nameStart = nameEnd - rawName.length;
718
+ if (scan.slice(nameStart, nameEnd) !== rawName)
719
+ continue;
720
+ const close = matchingParen(scan, parenIndex);
721
+ if (close < 0 || !CTE_BODY_RE.test(scan.slice(close + 1)))
722
+ continue;
723
+ excluded.add(nameStart);
724
+ }
725
+ collectSourceItemExclusions(scan, excluded);
726
+ excludeInsertTargets(scan, excluded);
727
+ collectCreateTableColumnShapes(scan, excluded, computed);
728
+ return excluded;
729
+ }
730
+ /**
731
+ * `SELECT call audit_user FROM contacts` selects a column named `call` and aliases it. No statement
732
+ * starts right after `SELECT`, a comma, or an opening parenthesis, so a keyword there is a column, and
733
+ * a comment in between changes nothing. A string does: `masked` blanks strings as well as comments, but
734
+ * `SELECT 'x'` followed by `EXEC p` in a T-SQL script without semicolons does start a statement. Only
735
+ * whitespace and comments may sit between the keyword and the token before it.
736
+ */
737
+ function followsExpressionStart(statementText, masked, keywordStart) {
738
+ let cursor = keywordStart;
739
+ while (cursor > 0 && /\s/.test(masked[cursor - 1] ?? ""))
740
+ cursor -= 1;
741
+ if (skipTrivia(statementText, cursor) !== keywordStart)
742
+ return false;
743
+ const before = masked[cursor - 1];
744
+ if (before === "," || before === "(")
745
+ return true;
746
+ const word = previousWord(masked, cursor);
747
+ return word === "select" || word === "distinct";
748
+ }
749
+ function collectCallKeywordMentions(statementText, masked, scan, mentions, inBody) {
750
+ for (const match of scan.matchAll(CALL_KEYWORD_RE)) {
751
+ // `EXECUTE cmd` in a PL/pgSQL body names a variable that holds a command, not a routine.
752
+ if (inBody && hasWord(EXECUTE_WORDS, (match[1] ?? "").toLowerCase()))
753
+ continue;
754
+ const matchStart = match.index ?? 0;
755
+ if (followsExpressionStart(statementText, masked, matchStart))
756
+ continue;
757
+ const end = matchStart + match[0].length;
758
+ if (!callKeywordMatchAllowsComments(statementText, masked.slice(matchStart, end), matchStart))
759
+ continue;
760
+ const start = end - (match[2] ?? "").length;
761
+ const name = normalizeSqlObjectName(masked.slice(start, end));
762
+ if (!name || (!name.includes(".") && hasWord(NON_ROUTINE_NAME_WORDS, name.toLowerCase())))
763
+ continue;
764
+ if (mentions.has(start))
765
+ continue;
766
+ mentions.set(start, { name, start, end, kind: "call", namespace: "callable", speculative: false });
767
+ }
768
+ }
769
+ /** `FILTER (WHERE ...)` filters an aggregate. It is not a call of a routine named filter. */
770
+ function isAggregateFilterClause(scan, nameEnd) {
771
+ const open = skipWhitespace(scan, nameEnd);
772
+ if (scan.charCodeAt(open) !== 40)
773
+ return false;
774
+ return wordAt(scan, skipWhitespace(scan, open + 1)) === "where";
775
+ }
776
+ /** Clause syntax resembles a call only at its keyword position, never everywhere that name occurs. */
777
+ function isCallShapedClause(scan, start, end, word) {
778
+ if (!word || !isBareSqlKeyword(scan, start, end))
779
+ return false;
780
+ if (word === "conflict")
781
+ return previousBareSqlWord(scan, start) === "on";
782
+ if (word === "group")
783
+ return previousBareSqlWord(scan, start) === "within";
784
+ if (word === "filter")
785
+ return isAggregateFilterClause(scan, end);
786
+ if (word !== "over")
787
+ return false;
788
+ let before = start - 1;
789
+ while (before >= 0 && /\s/.test(scan[before] ?? ""))
790
+ before -= 1;
791
+ return scan[before] === ")";
792
+ }
793
+ function collectCallShapeMentions(masked, scan, mentions, inBody) {
794
+ const computed = new Set();
795
+ const excluded = excludedCallShapeStarts(scan, computed);
796
+ for (const match of scan.matchAll(CALL_SHAPE_RE)) {
797
+ const start = match.index ?? 0;
798
+ if (mentions.has(start) || excluded.has(start))
799
+ continue;
800
+ const previous = previousBareSqlWord(scan, start);
801
+ // In a PL/pgSQL body `EXECUTE f(x)` calls `f` to build the command.
802
+ const buildsCommand = inBody && !!previous && hasWord(EXECUTE_WORDS, previous);
803
+ if (previous &&
804
+ hasWord(NON_CALL_PRECEDING_WORDS, previous) &&
805
+ !buildsCommand &&
806
+ !(previous === "as" && computed.has(start)))
807
+ continue;
808
+ const end = start + (match[1] ?? "").length;
809
+ const name = normalizeSqlObjectName(masked.slice(start, end));
810
+ if (!name)
811
+ continue;
812
+ const word = name.includes(".") ? "" : name.toLowerCase();
813
+ if (word && (hasWord(CALL_KEYWORDS, word) || word === "cast"))
814
+ continue;
815
+ if (isCallShapedClause(scan, start, end, word))
816
+ continue;
817
+ mentions.set(start, { name, start, end, kind: "call", namespace: "callable", speculative: true });
818
+ }
819
+ }
820
+ /**
821
+ * Finds every place one statement names a routine. A call inside a `$$` body or a `BEGIN ... END` body
822
+ * counts. A name inside a string literal, a comment, or a quoted identifier does not, and neither does
823
+ * the operand of a PL/pgSQL `EXECUTE`, which holds a command.
824
+ */
825
+ export function findSqlRoutineMentions(statementText) {
826
+ const { masked, inBody } = maskStatementCode(statementText);
827
+ // Names are read from `masked`. Keywords, calls, and parentheses are read from `scan`, where a
828
+ // quoted identifier is one bare word and nothing inside it can read as syntax.
829
+ const scan = maskSqlQuotedIdentifiers(masked);
830
+ const mentions = new Map();
831
+ collectKeywordMentions(masked, scan, mentions);
832
+ collectCallKeywordMentions(statementText, masked, scan, mentions, inBody);
833
+ collectCallShapeMentions(masked, scan, mentions, inBody);
834
+ return [...mentions.values()].sort((left, right) => left.start - right.start);
835
+ }
836
+ /**
837
+ * The routines one statement calls as sources. A column qualified with a source's alias, or with its
838
+ * own name when it has none, as in `SELECT get_users.id FROM get_users()`, belongs to the routine's
839
+ * result and not to a table of that name.
840
+ */
841
+ export function findSqlRoutineSources(statementText) {
842
+ const { masked } = maskStatementCode(statementText);
843
+ const calls = [];
844
+ collectSourceItemExclusions(maskSqlQuotedIdentifiers(masked), new Set(), calls);
845
+ const sources = [];
846
+ for (const call of calls) {
847
+ const named = nameAt(masked, call.start);
848
+ if (!named)
849
+ continue;
850
+ const alias = call.aliasStart === null ? null : (nameAt(masked, call.aliasStart)?.name ?? null);
851
+ sources.push({ mention: { ...named, kind: "call", namespace: "callable", speculative: true }, alias });
852
+ }
853
+ return sources;
854
+ }
855
+ /** The name space of the routine that a `CREATE FUNCTION`, `CREATE PROCEDURE`, or `CREATE TRIGGER` statement defines. */
856
+ export function sqlRoutineDefinitionNamespace(statementText) {
857
+ const keyword = SQL_ROUTINE_DEFINITION_RE.exec(maskSqlStringsAndComments(statementText))?.[1];
858
+ return keyword?.toLowerCase() === "trigger" ? "trigger" : "callable";
859
+ }
860
+ /**
861
+ * True for `DROP FUNCTION`, `DROP PROCEDURE`, and `DROP TRIGGER`. Fact extraction records the dropped
862
+ * name as a `drops_object` fact, which says nothing about the kind of the object. A table of the same
863
+ * name is not dropped. A comment can sit between the words, so the check reads the masked text.
864
+ */
865
+ export function sqlStatementDropsRoutine(statementText) {
866
+ return /\bdrop\b/i.test(statementText) && DROP_ROUTINE_RE.test(maskSqlStringsAndComments(statementText));
867
+ }
868
+ //# sourceMappingURL=routine-mentions.js.map