@backbencher/brain 0.0.0-stage → 0.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 (319) hide show
  1. package/CHANGELOG.md +298 -0
  2. package/EMBEDDINGS.md +355 -0
  3. package/LICENSE +21 -0
  4. package/README.md +415 -2
  5. package/bin/bb +13 -0
  6. package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
  7. package/dist/brain-index-health-Q5APTJQL.js +17 -0
  8. package/dist/brain-relationship-enrichment-MYR2AM4F.js +558 -0
  9. package/dist/brain.sql-EIM4WS4D.js +29 -0
  10. package/dist/chunk-22V37YTK.js +1758 -0
  11. package/dist/chunk-2BSKD7O3.js +40 -0
  12. package/dist/chunk-2DE27DVC.js +1314 -0
  13. package/dist/chunk-2RRBMNBQ.js +322 -0
  14. package/dist/chunk-2WXYNLBA.js +29 -0
  15. package/dist/chunk-3CTFIJJB.js +17 -0
  16. package/dist/chunk-3ZTOHHSW.js +2104 -0
  17. package/dist/chunk-4H22TLOT.js +543 -0
  18. package/dist/chunk-5BVAH26D.js +340 -0
  19. package/dist/chunk-62DHLYW6.js +3427 -0
  20. package/dist/chunk-7AN7U5IZ.js +371 -0
  21. package/dist/chunk-7DRPNVIN.js +782 -0
  22. package/dist/chunk-7MBYT777.js +174 -0
  23. package/dist/chunk-AHDWGM7Q.js +236 -0
  24. package/dist/chunk-B5GEAAYF.js +818 -0
  25. package/dist/chunk-BEIZZ73B.js +1479 -0
  26. package/dist/chunk-BQ3OVQ3P.js +125 -0
  27. package/dist/chunk-D2Q4Y47A.js +53 -0
  28. package/dist/chunk-DIYAGQJL.js +34 -0
  29. package/dist/chunk-DWKXZ6IF.js +336 -0
  30. package/dist/chunk-DYM4FQEE.js +90 -0
  31. package/dist/chunk-ENW4BTBA.js +930 -0
  32. package/dist/chunk-EWMWK7WN.js +75 -0
  33. package/dist/chunk-EY5ZZUUA.js +626 -0
  34. package/dist/chunk-GBI7V7KY.js +69 -0
  35. package/dist/chunk-GEFFO6O2.js +152 -0
  36. package/dist/chunk-HJEWO5EV.js +247 -0
  37. package/dist/chunk-HQSPJDHI.js +613 -0
  38. package/dist/chunk-KAET47ZL.js +125 -0
  39. package/dist/chunk-KCDECRJY.js +440 -0
  40. package/dist/chunk-L5TDYKYK.js +76 -0
  41. package/dist/chunk-MLKGABMK.js +9 -0
  42. package/dist/chunk-NO3U3FJQ.js +201 -0
  43. package/dist/chunk-OWISBAOF.js +61 -0
  44. package/dist/chunk-QKTRECYS.js +1119 -0
  45. package/dist/chunk-QLK6ED4Q.js +235 -0
  46. package/dist/chunk-R2GW4F6R.js +19 -0
  47. package/dist/chunk-RCMTFSEF.js +87 -0
  48. package/dist/chunk-RM3PY6TG.js +376 -0
  49. package/dist/chunk-ROMM6KMC.js +433 -0
  50. package/dist/chunk-SGGCSHAX.js +12050 -0
  51. package/dist/chunk-SK6YVHFZ.js +211 -0
  52. package/dist/chunk-SM7RFQRO.js +214 -0
  53. package/dist/chunk-UGR4QIGS.js +67 -0
  54. package/dist/chunk-UQNQZXHY.js +711 -0
  55. package/dist/chunk-UUNHHX4M.js +13 -0
  56. package/dist/chunk-VL52PL2T.js +71 -0
  57. package/dist/chunk-WIG36E67.js +196 -0
  58. package/dist/chunk-XHK3WWGB.js +7436 -0
  59. package/dist/chunk-XTQM2IP3.js +2863 -0
  60. package/dist/chunk-ZE2LG76D.js +1296 -0
  61. package/dist/chunk-ZETTGPAW.js +6950 -0
  62. package/dist/cli/index.js +37 -0
  63. package/dist/config-HZAAYDP3.js +10 -0
  64. package/dist/content-search-7XIP555Q.js +593 -0
  65. package/dist/database-76RP44JG.js +9 -0
  66. package/dist/doctor-ANGETYMN.js +395 -0
  67. package/dist/edit-engine-CG72LDZD.js +51 -0
  68. package/dist/engine-BKEOGN7N.js +11 -0
  69. package/dist/engine-VIW6NSKO.js +18 -0
  70. package/dist/fingerprint-OBLIMZLP.js +33 -0
  71. package/dist/framework-intelligence-3LORTPOX.js +860 -0
  72. package/dist/freshness-3K6VU5OT.js +174 -0
  73. package/dist/graph-engine-HBSQNPTB.js +21 -0
  74. package/dist/graph_request-Q6NKB6N2.js +350 -0
  75. package/dist/impact_request-LYP672WE.js +68 -0
  76. package/dist/index-space-IUUN5WYV.js +15 -0
  77. package/dist/index-status-7OVGYSGW.js +34 -0
  78. package/dist/index.js +159 -0
  79. package/dist/instance-FO6QZRLH.js +19 -0
  80. package/dist/language-detection-DFCAU5DZ.js +11 -0
  81. package/dist/lsp/server.js +4301 -0
  82. package/dist/mcp/server.js +132 -0
  83. package/dist/onboard-DIQZV2NW.js +161 -0
  84. package/dist/override-companion-pass-XR7MHTP7.js +117 -0
  85. package/dist/parallel-indexer-FK2XKZXY.js +88 -0
  86. package/dist/pool-worker.js +1153 -0
  87. package/dist/project-health-6XPENVAA.js +94 -0
  88. package/dist/project-index-5SDPHITE.js +57 -0
  89. package/dist/project-registry-ZJ3DVUGO.js +355 -0
  90. package/dist/real-bash-analyzer-EJAU5LW5.js +2201 -0
  91. package/dist/real-c-analyzer-HBD3FNNH.js +5942 -0
  92. package/dist/real-clean-analyzer-4EEZLPV5.js +3470 -0
  93. package/dist/real-clojure-analyzer-Q55EBOO2.js +2818 -0
  94. package/dist/real-cpp-analyzer-IVVOD25R.js +4101 -0
  95. package/dist/real-csharp-analyzer-ZBNLNJZJ.js +3298 -0
  96. package/dist/real-css-analyzer-6XRQLUN7.js +15 -0
  97. package/dist/real-dart-analyzer-OLR72EFW.js +3944 -0
  98. package/dist/real-elixir-analyzer-MQWGAH2I.js +2192 -0
  99. package/dist/real-erlang-analyzer-7BVPQEHO.js +1731 -0
  100. package/dist/real-fsharp-analyzer-C2UPFNOA.js +2390 -0
  101. package/dist/real-go-analyzer-UKGI43YS.js +4126 -0
  102. package/dist/real-graphql-analyzer-VE2EEFII.js +1442 -0
  103. package/dist/real-groovy-analyzer-W26VACFW.js +2285 -0
  104. package/dist/real-haskell-analyzer-5CVVAJRX.js +2533 -0
  105. package/dist/real-hcl-analyzer-5ZT4U43N.js +725 -0
  106. package/dist/real-html-analyzer-JWNX3C6I.js +1759 -0
  107. package/dist/real-java-analyzer-GU42VBGQ.js +4677 -0
  108. package/dist/real-javascript-analyzer-QA4QOJ6W.js +14 -0
  109. package/dist/real-json-analyzer-MPA6PRXL.js +1640 -0
  110. package/dist/real-julia-analyzer-22CWYQMN.js +2085 -0
  111. package/dist/real-kotlin-analyzer-QDZJLXXU.js +3956 -0
  112. package/dist/real-lua-analyzer-G7NHLYKS.js +1957 -0
  113. package/dist/real-makefile-analyzer-OCY3GT5N.js +920 -0
  114. package/dist/real-markdown-analyzer-TEJK2JXJ.js +1215 -0
  115. package/dist/real-matlab-analyzer-Q5SWLN7Z.js +480 -0
  116. package/dist/real-nim-analyzer-YLXSK563.js +3603 -0
  117. package/dist/real-objective-c-analyzer-D23ACC2R.js +1518 -0
  118. package/dist/real-perl-analyzer-WWTRHYDT.js +1865 -0
  119. package/dist/real-php-analyzer-JNKJHTCL.js +9368 -0
  120. package/dist/real-powershell-analyzer-XRSNQERV.js +2915 -0
  121. package/dist/real-protobuf-analyzer-3OKUCZ7T.js +867 -0
  122. package/dist/real-python-analyzer-VXAFWI72.js +4880 -0
  123. package/dist/real-r-analyzer-ZGAIDVI4.js +2596 -0
  124. package/dist/real-ruby-analyzer-X2KTLVBH.js +2429 -0
  125. package/dist/real-rust-analyzer-OFFHPL2A.js +3359 -0
  126. package/dist/real-scala-analyzer-TSTW27J6.js +3293 -0
  127. package/dist/real-scss-analyzer-AVWYPSOQ.js +1515 -0
  128. package/dist/real-solidity-analyzer-UCI2KWUB.js +2608 -0
  129. package/dist/real-sql-analyzer-F77ZMQXR.js +3840 -0
  130. package/dist/real-svelte-analyzer-SF7NRUO5.js +2532 -0
  131. package/dist/real-swift-analyzer-MN5QT3QN.js +2311 -0
  132. package/dist/real-toml-analyzer-66L7BDCQ.js +929 -0
  133. package/dist/real-typescript-analyzer-6KEMVDWQ.js +14 -0
  134. package/dist/real-vb-analyzer-VICVPOP7.js +3145 -0
  135. package/dist/real-vba-analyzer-HXLTTHKM.js +466 -0
  136. package/dist/real-vue-analyzer-QXR56CFV.js +2680 -0
  137. package/dist/real-xml-analyzer-YL465ZJW.js +2405 -0
  138. package/dist/real-yaml-analyzer-SUBCBNSI.js +3528 -0
  139. package/dist/real-zig-analyzer-HIQLZMGY.js +2430 -0
  140. package/dist/regex-search-NJKHMZNO.js +239 -0
  141. package/dist/rules-ACHPB7QU.js +152 -0
  142. package/dist/scoped-path-MJYWJZQX.js +11 -0
  143. package/dist/setup-show-NT5ZHYNE.js +15 -0
  144. package/dist/setup-wizard-G5YYR5T6.js +24 -0
  145. package/dist/symbol-search-GZJIM2J2.js +16 -0
  146. package/dist/taint-KXUHHPIE.js +202 -0
  147. package/dist/taint-analyzer-N7YLZU3N.js +163 -0
  148. package/dist/tool-handlers-OJDC35DI.js +72 -0
  149. package/dist/tool-registry-BPEJNSZG.js +17 -0
  150. package/dist/tool-validation-Q57YMMBX.js +32 -0
  151. package/dist/type-inference-QMT2RMLV.js +13 -0
  152. package/dist/vector-binary-LMY4QGAN.js +19 -0
  153. package/dist/version-ABP2TUL2.js +9 -0
  154. package/dist/wasm-NMWO3WXY.js +16 -0
  155. package/docs/EMBEDDINGS.md +132 -0
  156. package/docs/README.md +178 -0
  157. package/docs/data/m10-baseline.json +602 -0
  158. package/docs/data/m10-benchmark-baseline.json +57 -0
  159. package/docs/data/m10-benchmark-last-run.json +127 -0
  160. package/docs/data/m10-final-audit.json +215 -0
  161. package/docs/data/m12-final-audit.json +138 -0
  162. package/docs/data/m12-surface-matrix.json +50 -0
  163. package/docs/data/public-tools.json +1902 -0
  164. package/docs/indexing/DEAD-ASSETS.md +88 -0
  165. package/docs/indexing/INDEXER-REVIEW.md +634 -0
  166. package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
  167. package/docs/indexing/README.md +427 -0
  168. package/docs/indexing/discovery-matrix.md +41 -0
  169. package/docs/indexing/embeddings.md +325 -0
  170. package/docs/indexing/environment-variables.md +77 -0
  171. package/docs/indexing/performance.md +323 -0
  172. package/docs/indexing/resume.md +345 -0
  173. package/docs/indexing/troubleshooting.md +391 -0
  174. package/docs/man/bb.1 +190 -0
  175. package/docs/tools/bb_analyze.md +147 -0
  176. package/docs/tools/bb_annotate.md +110 -0
  177. package/docs/tools/bb_annotations.md +106 -0
  178. package/docs/tools/bb_ask.md +101 -0
  179. package/docs/tools/bb_cross_language.md +103 -0
  180. package/docs/tools/bb_doc.md +169 -0
  181. package/docs/tools/bb_edit.md +185 -0
  182. package/docs/tools/bb_graph.md +169 -0
  183. package/docs/tools/bb_health.md +156 -0
  184. package/docs/tools/bb_impact.md +117 -0
  185. package/docs/tools/bb_index.md +108 -0
  186. package/docs/tools/bb_migrate.md +135 -0
  187. package/docs/tools/bb_patterns.md +140 -0
  188. package/docs/tools/bb_search.md +150 -0
  189. package/docs/tools/bb_security.md +100 -0
  190. package/docs/tools/bb_visualize.md +184 -0
  191. package/grammars/README.md +57 -0
  192. package/grammars/THIRD-PARTY-NOTICES.md +50 -0
  193. package/grammars/tree-sitter-c/LICENSE +21 -0
  194. package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
  195. package/grammars/tree-sitter-cpp/LICENSE +21 -0
  196. package/grammars/tree-sitter-csharp/LICENSE +21 -0
  197. package/grammars/tree-sitter-css/LICENSE +21 -0
  198. package/grammars/tree-sitter-css/README.md +21 -0
  199. package/grammars/tree-sitter-dart/LICENSE +20 -0
  200. package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
  201. package/grammars/tree-sitter-dart-upstream/README.md +18 -0
  202. package/grammars/tree-sitter-elixir/LICENSE +176 -0
  203. package/grammars/tree-sitter-elixir/README.md +11 -0
  204. package/grammars/tree-sitter-fsharp/LICENSE +21 -0
  205. package/grammars/tree-sitter-fsharp/README.md +45 -0
  206. package/grammars/tree-sitter-graphql/LICENSE +21 -0
  207. package/grammars/tree-sitter-graphql/README.md +106 -0
  208. package/grammars/tree-sitter-groovy/LICENSE +21 -0
  209. package/grammars/tree-sitter-groovy/README.md +4 -0
  210. package/grammars/tree-sitter-haskell/LICENSE +21 -0
  211. package/grammars/tree-sitter-haskell/README.md +394 -0
  212. package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
  213. package/grammars/tree-sitter-hcl/LICENSE +201 -0
  214. package/grammars/tree-sitter-hcl/README.md +39 -0
  215. package/grammars/tree-sitter-html/LICENSE +21 -0
  216. package/grammars/tree-sitter-html/README.md +21 -0
  217. package/grammars/tree-sitter-julia/LICENSE +21 -0
  218. package/grammars/tree-sitter-julia/README.md +24 -0
  219. package/grammars/tree-sitter-kotlin/LICENSE +9 -0
  220. package/grammars/tree-sitter-lua/LICENSE.md +21 -0
  221. package/grammars/tree-sitter-lua/README.md +29 -0
  222. package/grammars/tree-sitter-make/LICENSE +21 -0
  223. package/grammars/tree-sitter-matlab/LICENSE +19 -0
  224. package/grammars/tree-sitter-matlab/README.md +99 -0
  225. package/grammars/tree-sitter-nim/LICENSE +373 -0
  226. package/grammars/tree-sitter-nim/README.md +46 -0
  227. package/grammars/tree-sitter-objc/LICENSE +21 -0
  228. package/grammars/tree-sitter-objc/README.md +20 -0
  229. package/grammars/tree-sitter-perl/LICENSE +7 -0
  230. package/grammars/tree-sitter-perl/README.md +100 -0
  231. package/grammars/tree-sitter-powershell/LICENSE +21 -0
  232. package/grammars/tree-sitter-powershell/README.md +7 -0
  233. package/grammars/tree-sitter-proto/LICENSE +21 -0
  234. package/grammars/tree-sitter-proto/README.md +105 -0
  235. package/grammars/tree-sitter-r/LICENSE +9 -0
  236. package/grammars/tree-sitter-r/README.md +66 -0
  237. package/grammars/tree-sitter-ruby/LICENSE +22 -0
  238. package/grammars/tree-sitter-scss/LICENSE +21 -0
  239. package/grammars/tree-sitter-scss/README.md +17 -0
  240. package/grammars/tree-sitter-solidity/LICENSE +7 -0
  241. package/grammars/tree-sitter-sql/LICENSE +21 -0
  242. package/grammars/tree-sitter-typescript/LICENSE +21 -0
  243. package/grammars/tree-sitter-vba/LICENSE +21 -0
  244. package/grammars/tree-sitter-vba/README.md +738 -0
  245. package/grammars/tree-sitter-vbnet/LICENSE +21 -0
  246. package/grammars/tree-sitter-vbnet/README.md +322 -0
  247. package/grammars/tree-sitter-xml/LICENSE +19 -0
  248. package/grammars/tree-sitter-yaml/LICENSE +20 -0
  249. package/grammars/tree-sitter-yaml/README.md +21 -0
  250. package/package.json +184 -4
  251. package/wasm/dart.wasm +0 -0
  252. package/wasm/tree-sitter-bash.wasm +0 -0
  253. package/wasm/tree-sitter-c.wasm +0 -0
  254. package/wasm/tree-sitter-c_sharp.wasm +0 -0
  255. package/wasm/tree-sitter-clean.wasm +0 -0
  256. package/wasm/tree-sitter-clojure.wasm +0 -0
  257. package/wasm/tree-sitter-core_schema.wasm +0 -0
  258. package/wasm/tree-sitter-cpp.wasm +0 -0
  259. package/wasm/tree-sitter-css.wasm +0 -0
  260. package/wasm/tree-sitter-dart.wasm +0 -0
  261. package/wasm/tree-sitter-elisp.wasm +0 -0
  262. package/wasm/tree-sitter-elixir.wasm +0 -0
  263. package/wasm/tree-sitter-elm.wasm +0 -0
  264. package/wasm/tree-sitter-embedded_template.wasm +0 -0
  265. package/wasm/tree-sitter-erlang.wasm +0 -0
  266. package/wasm/tree-sitter-fsharp.wasm +0 -0
  267. package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
  268. package/wasm/tree-sitter-go.wasm +0 -0
  269. package/wasm/tree-sitter-graphql.wasm +0 -0
  270. package/wasm/tree-sitter-groovy.wasm +0 -0
  271. package/wasm/tree-sitter-haskell.wasm +0 -0
  272. package/wasm/tree-sitter-hcl.wasm +0 -0
  273. package/wasm/tree-sitter-html.wasm +0 -0
  274. package/wasm/tree-sitter-java.wasm +0 -0
  275. package/wasm/tree-sitter-javascript.wasm +0 -0
  276. package/wasm/tree-sitter-json.wasm +0 -0
  277. package/wasm/tree-sitter-json_schema.wasm +0 -0
  278. package/wasm/tree-sitter-julia.wasm +0 -0
  279. package/wasm/tree-sitter-kotlin.wasm +0 -0
  280. package/wasm/tree-sitter-lua.wasm +0 -0
  281. package/wasm/tree-sitter-make.wasm +0 -0
  282. package/wasm/tree-sitter-markdown.wasm +0 -0
  283. package/wasm/tree-sitter-markdown_inline.wasm +0 -0
  284. package/wasm/tree-sitter-matlab.wasm +0 -0
  285. package/wasm/tree-sitter-nim.wasm +0 -0
  286. package/wasm/tree-sitter-objc.wasm +0 -0
  287. package/wasm/tree-sitter-ocaml.wasm +0 -0
  288. package/wasm/tree-sitter-perl.wasm +0 -0
  289. package/wasm/tree-sitter-php.wasm +0 -0
  290. package/wasm/tree-sitter-php_only.wasm +0 -0
  291. package/wasm/tree-sitter-powershell.wasm +0 -0
  292. package/wasm/tree-sitter-protobuf.wasm +0 -0
  293. package/wasm/tree-sitter-python.wasm +0 -0
  294. package/wasm/tree-sitter-ql.wasm +0 -0
  295. package/wasm/tree-sitter-r.wasm +0 -0
  296. package/wasm/tree-sitter-rescript.wasm +0 -0
  297. package/wasm/tree-sitter-ruby.wasm +0 -0
  298. package/wasm/tree-sitter-rust.wasm +0 -0
  299. package/wasm/tree-sitter-scala.wasm +0 -0
  300. package/wasm/tree-sitter-scss.wasm +0 -0
  301. package/wasm/tree-sitter-solidity.wasm +0 -0
  302. package/wasm/tree-sitter-sql.wasm +0 -0
  303. package/wasm/tree-sitter-svelte.wasm +0 -0
  304. package/wasm/tree-sitter-swift.wasm +0 -0
  305. package/wasm/tree-sitter-systemrdl.wasm +0 -0
  306. package/wasm/tree-sitter-terraform.wasm +0 -0
  307. package/wasm/tree-sitter-tlaplus.wasm +0 -0
  308. package/wasm/tree-sitter-toml.wasm +0 -0
  309. package/wasm/tree-sitter-tsx.wasm +0 -0
  310. package/wasm/tree-sitter-typescript.wasm +0 -0
  311. package/wasm/tree-sitter-vba.wasm +0 -0
  312. package/wasm/tree-sitter-vbnet.wasm +0 -0
  313. package/wasm/tree-sitter-vue.wasm +0 -0
  314. package/wasm/tree-sitter-xml.wasm +0 -0
  315. package/wasm/tree-sitter-yaml.wasm +0 -0
  316. package/wasm/tree-sitter-zig.wasm +0 -0
  317. package/wasm/tree-sitter.wasm +0 -0
  318. package/wasm/tsx.wasm +0 -0
  319. package/wasm/typescript.wasm +0 -0
@@ -0,0 +1,1442 @@
1
+ import {
2
+ FILE_CLAIM_MAX_BYTES,
3
+ fileClaimForTarget
4
+ } from "./chunk-EWMWK7WN.js";
5
+ import {
6
+ ASTEngine
7
+ } from "./chunk-3ZTOHHSW.js";
8
+ import "./chunk-BQ3OVQ3P.js";
9
+ import "./chunk-SK6YVHFZ.js";
10
+ import "./chunk-2BSKD7O3.js";
11
+ import "./chunk-KAET47ZL.js";
12
+ import "./chunk-KCDECRJY.js";
13
+ import "./chunk-MLKGABMK.js";
14
+
15
+ // src/ast/real-graphql-analyzer.ts
16
+ var EXTENSION_TO_DEFINITION = {
17
+ ObjectTypeExtension: "ObjectTypeDefinition",
18
+ InterfaceTypeExtension: "InterfaceTypeDefinition",
19
+ UnionTypeExtension: "UnionTypeDefinition",
20
+ EnumTypeExtension: "EnumTypeDefinition",
21
+ ScalarTypeExtension: "ScalarTypeDefinition",
22
+ InputObjectTypeExtension: "InputObjectTypeDefinition"
23
+ };
24
+ var SPEC_BUILTIN_SCALARS = ["String", "Int", "Float", "Boolean", "ID"];
25
+ var SPEC_BUILTIN_SCALAR_SET = new Set(SPEC_BUILTIN_SCALARS);
26
+ function lastPathSegment(p) {
27
+ let cut = -1;
28
+ for (let i = 0; i < p.length; i++) {
29
+ const c = p.charAt(i);
30
+ if (c === "/" || c === "\\") cut = i;
31
+ }
32
+ return cut >= 0 ? p.slice(cut + 1) : p;
33
+ }
34
+ function unnamedOperationIdentity(filePath, ordinal) {
35
+ const base = lastPathSegment(filePath ?? "");
36
+ const dot = base.lastIndexOf(".");
37
+ const stem = dot > 0 ? base.slice(0, dot) : base;
38
+ return `${stem || "document"}::operation_${ordinal}`;
39
+ }
40
+ var HASH_IMPORT_KEYWORD = "import";
41
+ var isQuote = (code) => code === 34 || code === 39 || code === 96;
42
+ var isInlineSpace = (code) => code === 32 || code === 9;
43
+ var isWordByte = (code) => code >= 65 && code <= 90 || code >= 97 && code <= 122 || code >= 48 && code <= 57 || code === 95;
44
+ function parseHashImport(text) {
45
+ let i = 0;
46
+ while (i < text.length && isInlineSpace(text.charCodeAt(i))) i++;
47
+ if (text.charCodeAt(i) !== 35) return null;
48
+ i++;
49
+ while (i < text.length && isInlineSpace(text.charCodeAt(i))) i++;
50
+ for (let k = 0; k < HASH_IMPORT_KEYWORD.length; k++) {
51
+ if (text.charCodeAt(i + k) !== HASH_IMPORT_KEYWORD.charCodeAt(k)) return null;
52
+ }
53
+ i += HASH_IMPORT_KEYWORD.length;
54
+ if (i < text.length && isWordByte(text.charCodeAt(i))) return null;
55
+ const skipSpace = () => {
56
+ while (i < text.length && isInlineSpace(text.charCodeAt(i))) i++;
57
+ };
58
+ const quoted = () => {
59
+ skipSpace();
60
+ const q = text.charCodeAt(i);
61
+ if (!isQuote(q)) return null;
62
+ i++;
63
+ const start = i;
64
+ while (i < text.length && text.charCodeAt(i) !== q) i++;
65
+ if (i >= text.length) return null;
66
+ const value = text.slice(start, i);
67
+ i++;
68
+ return value.length > 0 ? value : null;
69
+ };
70
+ const word = () => {
71
+ skipSpace();
72
+ const s = i;
73
+ while (i < text.length && !isInlineSpace(text.charCodeAt(i)) && !isQuote(text.charCodeAt(i)) && text.charCodeAt(i) !== 44) i++;
74
+ return text.slice(s, i);
75
+ };
76
+ const first = quoted();
77
+ if (first !== null) {
78
+ const after = word();
79
+ if (after.length === 0) return { target: first, form: "bare", bindings: [] };
80
+ return after === "as" ? { target: first, form: "bare", bindings: [word()] } : null;
81
+ }
82
+ const bindings = [];
83
+ for (; ; ) {
84
+ const w = word();
85
+ if (w.length === 0) return null;
86
+ bindings.push(w);
87
+ if (text.charCodeAt(i) === 44) {
88
+ i++;
89
+ continue;
90
+ }
91
+ break;
92
+ }
93
+ if (word() !== "from") return null;
94
+ const target = quoted();
95
+ if (target === null) return null;
96
+ return { target, form: "from_binding", bindings };
97
+ }
98
+ var DIRECTIVE_NODE = /* @__PURE__ */ new WeakMap();
99
+ var RealGraphqlAnalyzer = class _RealGraphqlAnalyzer {
100
+ /**
101
+ * `node.type` memoised per node id, for the duration of one `analyze` call.
102
+ *
103
+ * `type` is a marshalling getter — every read crosses into WASM and copies a
104
+ * string out — and the analyzer reads it far more often than there are nodes:
105
+ * measured on the 20,368-line GitHub public schema, **103,531 reads of 31,491
106
+ * distinct nodes, so 69.6% were redundant.** `node.id`, by contrast, is a plain
107
+ * own property set in the binding's constructor, so keying a `Map` on it costs
108
+ * nothing and turns every read after the first into a hash lookup.
109
+ *
110
+ * It is an instance field only because the readers are instance methods, and it
111
+ * is REASSIGNED at the top of every `analyze` call, which is what makes it safe:
112
+ * a `Node` id is only unique within one tree, and the binding documents that a
113
+ * node reused from an older tree keeps its id, so a cache that outlived a call
114
+ * could answer with the previous tree's type. Reassigning makes that impossible
115
+ * rather than merely unlikely.
116
+ */
117
+ typeCache = /* @__PURE__ */ new Map();
118
+ /** Counts the operations this document leaves unnamed, so each can be published under
119
+ * the file's identity (see `unnamedOperationIdentity`). Reset per `analyze` call: a
120
+ * pooled worker reuses one analyzer instance across files, and a counter that
121
+ * survived the call would number the second file's operations from where the first
122
+ * file stopped. */
123
+ unnamedOperationOrdinal = 0;
124
+ /** `node.type`, read through the per-call memo. */
125
+ typeOf(node) {
126
+ const id = node.id;
127
+ if (typeof id !== "number") return node.type;
128
+ const hit = this.typeCache.get(id);
129
+ if (hit !== void 0) return hit;
130
+ const t = node.type;
131
+ this.typeCache.set(id, t);
132
+ return t;
133
+ }
134
+ analyze(rootNode, content, filePath, context) {
135
+ this.typeCache = /* @__PURE__ */ new Map();
136
+ this.unnamedOperationOrdinal = 0;
137
+ const symbols = [];
138
+ const relationships = [];
139
+ const imports = [];
140
+ const exports = [];
141
+ const errors = [];
142
+ const relKeys = /* @__PURE__ */ new Set();
143
+ const addRelationship = (source, target, type, line, role, metadata = {}) => {
144
+ if (source === target && role === "field_selection") return;
145
+ if (!source || !target) return;
146
+ const key = `${source}\0${type}\0${target}\0${role}\0${line}`;
147
+ if (relKeys.has(key)) return;
148
+ relKeys.add(key);
149
+ relationships.push({
150
+ source,
151
+ target,
152
+ type,
153
+ confidence: 1,
154
+ line_number: line,
155
+ // Every edge this analyzer emits is read off a NAMED AST NODE — an
156
+ // `ImplementsInterfaces` clause, a `NamedType`, a field's own `Name`, a
157
+ // `Directives` child — so `structural` is the class for most of them and is
158
+ // stated rather than left absent. 38 sibling lanes publish this key and this
159
+ // one published none, which made "how much of this graph is guesswork" a
160
+ // question with no machine-readable answer on this lane: the honesty contract
161
+ // §4.3 requires the heuristic ratio to be a QUERYABLE number, and an absent
162
+ // key is not queryable. `confidence` was already 1 everywhere, so nothing
163
+ // here is newly a heuristic — the key says so explicitly.
164
+ //
165
+ // THE ONE TIER THAT IS NOT STRUCTURAL: `imports`. A `#import "file.graphql"`
166
+ // hash-import's TARGET is a FILE PATH read out of a comment string, not a name
167
+ // read off a named AST node — it is the lane's file-dependency claim (the same
168
+ // ladder toml's imports row carries), so it is `import_based`. Section D of the
169
+ // completeness inventory requires two DISTINCT tiers pinned by fixtures, and
170
+ // this is the lane's honest second one rather than a manufactured value.
171
+ metadata: {
172
+ ...metadata,
173
+ relationshipRole: role,
174
+ evidenceClass: type === ASTEngine.RelationshipType.Imports ? "import_based" : "structural"
175
+ }
176
+ });
177
+ };
178
+ const addDeclaredType = (source, target, line, role, metadata = {}) => {
179
+ addRelationship(source, target, ASTEngine.RelationshipType.References, line, role, {
180
+ ...metadata,
181
+ relationshipType: "declared_type",
182
+ // THE CLAIM — attached HERE and nowhere else, because this closure is the ONE place every
183
+ // declared-type position passes through (directive argument, field return, field argument,
184
+ // input field, variable) and the only place where `target` is guaranteed to be a TYPE NAME
185
+ // rather than a member spelling. A union member list, an export row and a field selection are
186
+ // NOT type clauses, so the 48 edges of those shapes whose target happens to spell one of the
187
+ // five are left alone and stay `unresolved` — a measured boundary, not an oversight.
188
+ //
189
+ // The reason travels WITH the claim (`languageNamespaceBasis`) so the disposition can be read
190
+ // off the edge; it is not a key any claim channel reads, so it cannot misfire.
191
+ ...SPEC_BUILTIN_SCALAR_SET.has(target) ? {
192
+ languageNamespace: [...SPEC_BUILTIN_SCALARS],
193
+ languageNamespaceBasis: "graphql-spec-builtin-scalar"
194
+ } : {}
195
+ });
196
+ };
197
+ const directiveCache = /* @__PURE__ */ new WeakMap();
198
+ const directivesOf = (node) => {
199
+ const cached = directiveCache.get(node);
200
+ if (cached !== void 0) return cached;
201
+ const list = this.scanDirectiveApplications(node);
202
+ directiveCache.set(node, list);
203
+ return list;
204
+ };
205
+ const declaredHere = /* @__PURE__ */ new Set();
206
+ const kindOfNameHere = /* @__PURE__ */ new Map();
207
+ for (const decl of this.topLevelDeclarations(rootNode)) {
208
+ if (!decl.name) continue;
209
+ declaredHere.add(`${decl.symbolKind}\0${decl.name}`);
210
+ const kinds = kindOfNameHere.get(decl.name) ?? /* @__PURE__ */ new Set();
211
+ kinds.add(decl.symbolKind);
212
+ kindOfNameHere.set(decl.name, kinds);
213
+ }
214
+ const supertypeKindOf = (supertype) => {
215
+ const kinds = kindOfNameHere.get(supertype);
216
+ if (!kinds || kinds.size !== 1) return void 0;
217
+ const only = [...kinds][0];
218
+ return only === ASTEngine.SymbolKind.Interface || only === ASTEngine.SymbolKind.Class || only === ASTEngine.SymbolKind.Type ? only : void 0;
219
+ };
220
+ const emitHeritage = (owner, supertype, line, inExtension) => {
221
+ const supertypeKind = supertypeKindOf(supertype);
222
+ const relType = supertypeKind === ASTEngine.SymbolKind.Class || supertypeKind === ASTEngine.SymbolKind.Type ? ASTEngine.RelationshipType.Extends : ASTEngine.RelationshipType.Implements;
223
+ heritageEdges.push({ owner, iface: supertype, ifaceKind: supertypeKind });
224
+ addRelationship(owner, supertype, relType, line, relType === ASTEngine.RelationshipType.Extends ? "extends" : "implements", {
225
+ ...relType === ASTEngine.RelationshipType.Extends ? { implementsClause: true } : {},
226
+ ...inExtension ? { extension: true } : {}
227
+ });
228
+ };
229
+ const heritageEdges = [];
230
+ const memberNameNodes = /* @__PURE__ */ new Map();
231
+ const extendedHere = /* @__PURE__ */ new Set();
232
+ for (const ext of this.topLevelExtensions(rootNode)) {
233
+ extendedHere.add(`${ext.symbolKind}\0${ext.name}`);
234
+ }
235
+ const TYPE_KIND = {
236
+ ObjectTypeDefinition: ASTEngine.SymbolKind.Class,
237
+ InterfaceTypeDefinition: ASTEngine.SymbolKind.Interface,
238
+ UnionTypeDefinition: ASTEngine.SymbolKind.Type,
239
+ EnumTypeDefinition: ASTEngine.SymbolKind.Enum,
240
+ ScalarTypeDefinition: ASTEngine.SymbolKind.Type,
241
+ InputObjectTypeDefinition: ASTEngine.SymbolKind.Class
242
+ };
243
+ const extensionSymbols = [];
244
+ const rootOperationNames = /* @__PURE__ */ new Set();
245
+ const hashImports = [];
246
+ const stack = [
247
+ { node: rootNode, owner: {}, sel: { path: [] }, inExtension: false }
248
+ ];
249
+ const pushChildren = (node, owner, sel, inExtension, skip = () => false) => {
250
+ const kids = node.namedChildren;
251
+ for (let i = kids.length - 1; i >= 0; i--) {
252
+ const child = kids[i];
253
+ if (child && !skip(child)) stack.push({ node: child, owner, sel, inExtension });
254
+ }
255
+ };
256
+ if (this.isAnyOf(rootNode, "Document", "source_file", "SourceFile")) {
257
+ }
258
+ while (stack.length > 0) {
259
+ const { node, owner, sel, inExtension } = stack.pop();
260
+ const t = node.type;
261
+ if (t === "SchemaDefinition" || t === "SchemaExtension") {
262
+ if (!symbols.some((s) => s.name === "schema" && s.kind === ASTEngine.SymbolKind.Namespace)) {
263
+ symbols.push({
264
+ name: "schema",
265
+ kind: ASTEngine.SymbolKind.Namespace,
266
+ range: this.nodeToRange(node),
267
+ scope: "",
268
+ visibility: "public",
269
+ docstring: this.descriptionOf(node),
270
+ metadata: {
271
+ graphqlType: t === "SchemaDefinition" ? "schema" : "schema_extension",
272
+ topLevel: true,
273
+ ...t === "SchemaExtension" ? { inExtension: true } : {}
274
+ }
275
+ });
276
+ }
277
+ for (const opDef of node.namedChildren) {
278
+ if (opDef?.type !== "OperationTypeDefinition") continue;
279
+ const opTypeNode = this.firstChildOfType(opDef, "OperationType");
280
+ const opType = opTypeNode?.text ?? "operation";
281
+ const named = this.firstChildOfType(opDef, "NamedType");
282
+ const rootType = named ? this.nameOf(named) : void 0;
283
+ const line = this.lineOf(named ?? opDef);
284
+ if (rootOperationNames.has(opType)) continue;
285
+ rootOperationNames.add(opType);
286
+ symbols.push({
287
+ name: opType,
288
+ kind: ASTEngine.SymbolKind.Property,
289
+ range: this.nodeToRange(opDef),
290
+ scope: "schema",
291
+ visibility: "public",
292
+ returnType: rootType,
293
+ ownerName: "schema",
294
+ ownerKind: ASTEngine.SymbolKind.Namespace,
295
+ metadata: {
296
+ graphqlRole: "root_operation_type",
297
+ ...t === "SchemaExtension" ? { inExtension: true } : {}
298
+ }
299
+ });
300
+ addRelationship("schema", `schema.${opType}`, ASTEngine.RelationshipType.Contains, line, "contains", {
301
+ ...t === "SchemaExtension" ? { extension: true } : {}
302
+ });
303
+ if (rootType) {
304
+ addRelationship(`schema.${opType}`, rootType, ASTEngine.RelationshipType.Uses, line, "root_operation_type", {
305
+ ...t === "SchemaExtension" ? { extension: true } : {}
306
+ });
307
+ }
308
+ }
309
+ this.emitDirectiveApplications(node, directivesOf(node), "schema", sel, addRelationship, t === "SchemaExtension");
310
+ pushChildren(node, { name: "schema", kind: ASTEngine.SymbolKind.Namespace }, sel, inExtension, (c) => this.typeOf(c) === "OperationTypeDefinition");
311
+ continue;
312
+ }
313
+ if (TYPE_KIND[t]) {
314
+ const name = this.nameOf(node);
315
+ if (name) {
316
+ const kind = TYPE_KIND[t];
317
+ this.emitTypeSymbol(node, name, kind, t, symbols, relationships, sel, inExtension, directivesOf(node));
318
+ if (t === "ScalarTypeDefinition" && extendedHere.has(`${kind}\0${name}`)) {
319
+ const last = symbols[symbols.length - 1];
320
+ last.metadata = { ...last.metadata, extended: true };
321
+ }
322
+ const implNode = this.firstChildOfType(node, "ImplementsInterfaces");
323
+ if (implNode) {
324
+ for (const { name: iface, node: ifaceNode } of this.collectNamedTypes(implNode)) {
325
+ emitHeritage(name, iface, this.lineOf(ifaceNode), inExtension);
326
+ }
327
+ }
328
+ if (t === "UnionTypeDefinition") {
329
+ const membersNode = this.firstChildOfType(node, "UnionMemberTypes");
330
+ if (membersNode) {
331
+ for (const { name: member, node: memberNode } of this.collectNamedTypes(membersNode)) {
332
+ addRelationship(name, member, ASTEngine.RelationshipType.Uses, this.lineOf(memberNode), "union_member", {
333
+ ...inExtension ? { extension: true } : {}
334
+ });
335
+ }
336
+ }
337
+ }
338
+ this.emitDirectiveApplications(node, directivesOf(node), name, sel, addRelationship, inExtension);
339
+ pushChildren(node, { name, kind }, sel, inExtension);
340
+ }
341
+ continue;
342
+ }
343
+ if (EXTENSION_TO_DEFINITION[t]) {
344
+ if (t === "ScalarTypeExtension") {
345
+ this.emitDirectiveApplications(node, directivesOf(node), this.nameOf(node) ?? "", sel, addRelationship, true);
346
+ continue;
347
+ }
348
+ const definitionType = EXTENSION_TO_DEFINITION[t];
349
+ const name = this.nameOf(node);
350
+ if (name) {
351
+ const kind = TYPE_KIND[definitionType];
352
+ const kindKey = `${kind}\0${name}`;
353
+ if (!declaredHere.has(kindKey)) {
354
+ const index = symbols.length;
355
+ symbols.push({
356
+ name,
357
+ kind,
358
+ range: this.nodeToRange(node),
359
+ scope: "",
360
+ visibility: "public",
361
+ docstring: this.descriptionOf(node),
362
+ metadata: { graphqlType: t, partial: true, inExtension: true, topLevel: true }
363
+ });
364
+ extensionSymbols.push({ index, name, kindKey, typeNode: t });
365
+ }
366
+ const implNode = this.firstChildOfType(node, "ImplementsInterfaces");
367
+ if (implNode) {
368
+ for (const { name: iface, node: ifaceNode } of this.collectNamedTypes(implNode)) {
369
+ emitHeritage(name, iface, this.lineOf(ifaceNode), true);
370
+ }
371
+ }
372
+ if (definitionType === "UnionTypeDefinition") {
373
+ const membersNode = this.firstChildOfType(node, "UnionMemberTypes");
374
+ if (membersNode) {
375
+ for (const { name: member, node: memberNode } of this.collectNamedTypes(membersNode)) {
376
+ addRelationship(name, member, ASTEngine.RelationshipType.Uses, this.lineOf(memberNode), "union_member", { extension: true });
377
+ }
378
+ }
379
+ }
380
+ this.emitDirectiveApplications(node, directivesOf(node), name, sel, addRelationship, true);
381
+ pushChildren(node, { name, kind }, sel, true);
382
+ }
383
+ continue;
384
+ }
385
+ if (t === "EnumValueDefinition") {
386
+ const enumValue = this.firstChildOfType(node, "EnumValue");
387
+ const valueName = enumValue ? this.nameOf(enumValue) : void 0;
388
+ if (valueName && owner.name) {
389
+ symbols.push({
390
+ name: valueName,
391
+ kind: ASTEngine.SymbolKind.EnumMember,
392
+ range: this.nodeToRange(node),
393
+ scope: owner.name,
394
+ ownerName: owner.name,
395
+ ownerKind: owner.kind,
396
+ visibility: "public",
397
+ docstring: this.descriptionOf(node),
398
+ metadata: { graphqlRole: "enum_value", ...inExtension ? { inExtension: true } : {} }
399
+ });
400
+ addRelationship(owner.name, `${owner.name}.${valueName}`, ASTEngine.RelationshipType.Contains, this.lineOf(enumValue ?? node), "contains", {
401
+ ...inExtension ? { extension: true } : {}
402
+ });
403
+ this.emitDirectiveApplications(node, directivesOf(node), `${owner.name}.${valueName}`, { root: void 0 }, addRelationship, inExtension);
404
+ }
405
+ continue;
406
+ }
407
+ if (t === "DirectiveDefinition") {
408
+ const name = this.nameOf(node);
409
+ if (name) {
410
+ const argsNode = this.firstChildOfType(node, "ArgumentsDefinition");
411
+ const repeatable = this.hasChild(node, (n) => this.typeOf(n) === "repeatable");
412
+ const locations = this.firstChildOfType(node, "DirectiveLocations");
413
+ const locationNames = locations ? this.collectDirectiveLocations(locations).map((l) => l.name) : void 0;
414
+ symbols.push({
415
+ name: `@${name}`,
416
+ kind: ASTEngine.SymbolKind.Function,
417
+ range: this.nodeToRange(node),
418
+ scope: "",
419
+ visibility: "public",
420
+ parameters: argsNode ? this.extractArguments(argsNode) : [],
421
+ docstring: this.descriptionOf(node),
422
+ metadata: {
423
+ graphqlRole: "directive_definition",
424
+ topLevel: true,
425
+ directiveName: name,
426
+ ...repeatable ? { repeatable: true } : {},
427
+ ...locationNames ? { locations: locationNames } : {},
428
+ ...this.directiveMetadata(directivesOf(node))
429
+ }
430
+ });
431
+ if (argsNode) {
432
+ for (const arg of this.argumentPairs(argsNode)) {
433
+ if (!arg.type || !arg.typeNode) continue;
434
+ addDeclaredType(`@${name}`, arg.type, this.lineOf(arg.typeNode), "directive_argument_type", { argument: arg.name });
435
+ if (arg.name) this.emitEnumValueReferences(`@${name}`, arg.defaultNode, arg.type, addRelationship, { declaration: "directive_argument_default", argument: arg.name });
436
+ }
437
+ }
438
+ }
439
+ continue;
440
+ }
441
+ if (t === "FieldDefinition") {
442
+ const fieldName = this.nameOf(node);
443
+ if (fieldName && owner.name) {
444
+ const typeNode = this.firstChildOfType(node, "Type");
445
+ const returnType = typeNode ? this.namedTypeName(typeNode) : void 0;
446
+ const argsNode = this.firstChildOfType(node, "ArgumentsDefinition");
447
+ const ownerSymbol = `${owner.name}.${fieldName}`;
448
+ symbols.push({
449
+ name: fieldName,
450
+ kind: ASTEngine.SymbolKind.Property,
451
+ range: this.nodeToRange(node),
452
+ scope: owner.name,
453
+ visibility: "public",
454
+ returnType,
455
+ ownerName: owner.name,
456
+ ownerKind: owner.kind,
457
+ parameters: argsNode ? this.extractArguments(argsNode) : [],
458
+ docstring: this.descriptionOf(node),
459
+ metadata: {
460
+ graphqlRole: "field",
461
+ // `rawType` is the type EXPRESSION's source text and is emitted only
462
+ // when there is one: a recovered `Type` node with a MISSING `Name` has
463
+ // the empty text, and publishing `rawType: ""` is a fact about nothing.
464
+ ...typeNode && typeNode.text ? { rawType: typeNode.text } : {},
465
+ ...returnType ? { nullable: !this.isNonNullType(typeNode) } : {},
466
+ ...inExtension ? { inExtension: true } : {},
467
+ ...this.directiveMetadata(directivesOf(node))
468
+ }
469
+ });
470
+ const fieldNameNode = this.firstChildOfType(node, "Name");
471
+ addRelationship(owner.name, ownerSymbol, ASTEngine.RelationshipType.Contains, this.lineOf(fieldNameNode ?? node), "contains", {
472
+ ...inExtension ? { extension: true } : {}
473
+ });
474
+ if (fieldNameNode) {
475
+ const bag = memberNameNodes.get(owner.name) ?? /* @__PURE__ */ new Map();
476
+ if (!bag.has(fieldName)) bag.set(fieldName, fieldNameNode);
477
+ memberNameNodes.set(owner.name, bag);
478
+ }
479
+ if (returnType) {
480
+ addDeclaredType(ownerSymbol, returnType, this.lineOf(this.namedTypeNode(typeNode) ?? typeNode), "field_return_type", {
481
+ ...inExtension ? { extension: true } : {}
482
+ });
483
+ }
484
+ if (argsNode) {
485
+ for (const arg of this.argumentPairs(argsNode)) {
486
+ if (!arg.type || !arg.typeNode) continue;
487
+ addDeclaredType(ownerSymbol, arg.type, this.lineOf(arg.typeNode), "field_argument_type", {
488
+ argument: arg.name,
489
+ ...inExtension ? { extension: true } : {}
490
+ });
491
+ if (arg.name) this.emitEnumValueReferences(ownerSymbol, arg.defaultNode, arg.type, addRelationship, { declaration: "argument_default", argument: arg.name });
492
+ }
493
+ }
494
+ this.emitDirectiveApplications(node, directivesOf(node), ownerSymbol, sel, addRelationship, inExtension);
495
+ }
496
+ continue;
497
+ }
498
+ if (t === "InputValueDefinition" && node.parent?.type === "InputFieldsDefinition") {
499
+ const fieldName = this.nameOf(node);
500
+ if (fieldName && owner.name) {
501
+ const typeNode = this.firstChildOfType(node, "Type");
502
+ const fieldType = typeNode ? this.namedTypeName(typeNode) : void 0;
503
+ const ownerSymbol = `${owner.name}.${fieldName}`;
504
+ symbols.push({
505
+ name: fieldName,
506
+ kind: ASTEngine.SymbolKind.Property,
507
+ range: this.nodeToRange(node),
508
+ scope: owner.name,
509
+ visibility: "public",
510
+ returnType: fieldType,
511
+ ownerName: owner.name,
512
+ ownerKind: owner.kind,
513
+ docstring: this.descriptionOf(node),
514
+ metadata: {
515
+ graphqlRole: "input_field",
516
+ ...typeNode && typeNode.text ? { rawType: typeNode.text } : {},
517
+ ...fieldType ? { nullable: !this.isNonNullType(typeNode) } : {},
518
+ // Called ONCE. The conditional form below ran it twice per input
519
+ // field — a `firstChildOfType` walk each time — to test a value it
520
+ // then computed again, and this is the per-node hot path.
521
+ ...(() => {
522
+ const dv = this.defaultValueOf(node);
523
+ return dv !== void 0 ? { defaultValue: dv } : {};
524
+ })(),
525
+ ...inExtension ? { inExtension: true } : {},
526
+ ...this.directiveMetadata(directivesOf(node))
527
+ }
528
+ });
529
+ addRelationship(owner.name, ownerSymbol, ASTEngine.RelationshipType.Contains, this.lineOf(this.firstChildOfType(node, "Name") ?? node), "contains", {
530
+ ...inExtension ? { extension: true } : {}
531
+ });
532
+ this.emitEnumValueReferences(ownerSymbol, this.firstChildOfType(node, "DefaultValue"), fieldType, addRelationship, { declaration: "input_field_default" });
533
+ if (fieldType) {
534
+ addDeclaredType(ownerSymbol, fieldType, this.lineOf(this.namedTypeNode(typeNode) ?? typeNode), "input_field_type", {
535
+ ...inExtension ? { extension: true } : {}
536
+ });
537
+ }
538
+ this.emitDirectiveApplications(node, directivesOf(node), ownerSymbol, sel, addRelationship, inExtension);
539
+ }
540
+ continue;
541
+ }
542
+ if (t === "OperationDefinition") {
543
+ const opTypeNode = this.firstChildOfType(node, "OperationType");
544
+ const opType = opTypeNode?.text ?? "query";
545
+ const nameNode = this.firstChildOfType(node, "Name");
546
+ const opName = nameNode?.text ?? unnamedOperationIdentity(filePath, this.unnamedOperationOrdinal++);
547
+ symbols.push({
548
+ name: opName,
549
+ kind: ASTEngine.SymbolKind.Method,
550
+ range: this.nodeToRange(node),
551
+ scope: "",
552
+ visibility: "public",
553
+ metadata: {
554
+ graphqlRole: "operation",
555
+ graphqlOperationType: opType,
556
+ ...nameNode ? {} : { anonymous: true, shorthand: true }
557
+ }
558
+ });
559
+ const varsNode = this.firstChildOfType(node, "VariableDefinitions");
560
+ if (varsNode) {
561
+ for (const varDef of varsNode.namedChildren) {
562
+ if (varDef?.type !== "VariableDefinition") continue;
563
+ const varNode = this.firstChildOfType(varDef, "Variable");
564
+ const varName = varNode ? this.nameOf(varNode) : void 0;
565
+ const typeNode = this.firstChildOfType(varDef, "Type");
566
+ const varType = typeNode ? this.namedTypeName(typeNode) : void 0;
567
+ if (!varName) continue;
568
+ if (varType) {
569
+ addDeclaredType(`$${varName}`, varType, this.lineOf(this.namedTypeNode(typeNode) ?? typeNode), "variable_type", {
570
+ operation: opName
571
+ });
572
+ }
573
+ this.emitEnumValueReferences(`$${varName}`, this.firstChildOfType(varDef, "DefaultValue"), varType, addRelationship, { declaration: "variable_default" });
574
+ symbols.push({
575
+ name: `$${varName}`,
576
+ kind: ASTEngine.SymbolKind.Variable,
577
+ range: this.nodeToRange(varDef),
578
+ scope: opName,
579
+ returnType: varType,
580
+ ownerName: opName,
581
+ ownerKind: ASTEngine.SymbolKind.Method,
582
+ metadata: {
583
+ graphqlRole: "variable",
584
+ ...typeNode && typeNode.text ? { rawType: typeNode.text } : {},
585
+ ...varType ? { nullable: !this.isNonNullType(typeNode) } : {},
586
+ ...this.defaultValueOf(varDef) !== void 0 ? { defaultValue: this.defaultValueOf(varDef) } : {},
587
+ ...this.directiveMetadata(directivesOf(varDef))
588
+ }
589
+ });
590
+ }
591
+ }
592
+ this.emitDirectiveApplications(node, directivesOf(node), opName, sel, addRelationship, false);
593
+ if (varsNode) {
594
+ this.emitDirectiveApplications(varsNode, directivesOf(varsNode), opName, sel, addRelationship, false);
595
+ }
596
+ pushChildren(node, { name: opName, kind: ASTEngine.SymbolKind.Method }, { root: opName, path: [] }, inExtension, (c) => this.typeOf(c) === "VariableDefinition");
597
+ continue;
598
+ }
599
+ if (t === "FragmentDefinition") {
600
+ const fragNode = this.firstChildOfType(node, "FragmentName");
601
+ const fragName = fragNode ? this.nameOf(fragNode) : void 0;
602
+ if (fragName) {
603
+ symbols.push({
604
+ name: fragName,
605
+ kind: ASTEngine.SymbolKind.Method,
606
+ range: this.nodeToRange(node),
607
+ scope: "",
608
+ visibility: "public",
609
+ metadata: { graphqlRole: "fragment", ...this.directiveMetadata(directivesOf(node)) }
610
+ });
611
+ const typeCondition = this.firstChildOfType(node, "TypeCondition");
612
+ const onType = typeCondition ? this.namedTypeName(typeCondition) : void 0;
613
+ if (onType && typeCondition) {
614
+ addRelationship(fragName, onType, ASTEngine.RelationshipType.Uses, this.lineOf(this.namedTypeNode(typeCondition) ?? typeCondition), "fragment_type_condition");
615
+ }
616
+ this.emitDirectiveApplications(node, directivesOf(node), fragName, sel, addRelationship, false);
617
+ pushChildren(node, { name: fragName, kind: ASTEngine.SymbolKind.Method }, { root: fragName, enclosingType: onType, path: [] }, inExtension);
618
+ }
619
+ continue;
620
+ }
621
+ if (t === "VariableDefinition") continue;
622
+ if (t === "Field") {
623
+ const nameNode = this.firstChildOfType(node, "Name");
624
+ const fieldName = nameNode?.text;
625
+ const aliasNode = this.firstChildOfType(node, "Alias");
626
+ const alias = aliasNode ? this.nameOf(aliasNode) : void 0;
627
+ if (fieldName && sel.root) {
628
+ const qualified = sel.enclosingType ? `${sel.enclosingType}.${fieldName}` : fieldName;
629
+ const path = [...sel.path, fieldName].join(".");
630
+ const argsNode = this.firstChildOfType(node, "Arguments");
631
+ if (argsNode && sel.root) {
632
+ for (const arg of this.childrenOfType(argsNode, "Argument")) {
633
+ this.emitEnumValueReferences(sel.root, this.firstChildOfType(arg, "Value"), void 0, addRelationship, { declaration: "field_argument" });
634
+ }
635
+ }
636
+ addRelationship(sel.root, qualified, ASTEngine.RelationshipType.Uses, this.lineOf(nameNode), "field_selection", {
637
+ ...alias ? { alias } : {},
638
+ ...argsNode ? { arguments: this.argumentNames(argsNode) } : {},
639
+ ...sel.enclosingType ? { enclosingType: sel.enclosingType } : {},
640
+ ...path ? { selectionPath: path } : {}
641
+ });
642
+ }
643
+ this.emitDirectiveApplications(node, directivesOf(node), sel.root ?? "", sel, addRelationship, false);
644
+ const childPath = [...sel.path, fieldName ?? "?"];
645
+ pushChildren(node, { name: fieldName, kind: ASTEngine.SymbolKind.Property }, { root: sel.root, enclosingType: void 0, path: childPath }, inExtension, (c) => this.typeOf(c) === "Name" || this.typeOf(c) === "Alias");
646
+ continue;
647
+ }
648
+ if (t === "FragmentSpread") {
649
+ const spreadNode = this.firstChildOfType(node, "FragmentName");
650
+ const spreadName = spreadNode ? this.nameOf(spreadNode) : void 0;
651
+ if (spreadName && sel.root) {
652
+ addRelationship(sel.root, spreadName, ASTEngine.RelationshipType.Uses, this.lineOf(spreadNode), "fragment_spread", {
653
+ ...[...sel.path].length ? { selectionPath: sel.path.join(".") } : {}
654
+ });
655
+ }
656
+ this.emitDirectiveApplications(node, directivesOf(node), sel.root ?? "", sel, addRelationship, false);
657
+ continue;
658
+ }
659
+ if (t === "InlineFragment") {
660
+ const typeCondition = this.firstChildOfType(node, "TypeCondition");
661
+ const onType = typeCondition ? this.namedTypeName(typeCondition) : void 0;
662
+ if (onType && sel.root && typeCondition) {
663
+ addRelationship(sel.root, onType, ASTEngine.RelationshipType.Uses, this.lineOf(this.namedTypeNode(typeCondition) ?? typeCondition), "inline_fragment_type_condition", {
664
+ ...[...sel.path].length ? { selectionPath: sel.path.join(".") } : {}
665
+ });
666
+ }
667
+ this.emitDirectiveApplications(node, directivesOf(node), sel.root ?? "", sel, addRelationship, false);
668
+ pushChildren(node, { name: onType, kind: ASTEngine.SymbolKind.Type }, { root: sel.root, enclosingType: onType ?? sel.enclosingType, path: [...sel.path] }, inExtension, (c) => this.typeOf(c) === "TypeCondition");
669
+ continue;
670
+ }
671
+ if (t === "Variable") {
672
+ const valueParent = node.parent;
673
+ if (valueParent?.type === "Value" && sel.root) {
674
+ const varName = this.nameOf(node);
675
+ if (varName) {
676
+ addRelationship(sel.root, `$${varName}`, ASTEngine.RelationshipType.Uses, this.lineOf(node), "variable_reference", {
677
+ ...[...sel.path].length ? { selectionPath: sel.path.join(".") } : {}
678
+ });
679
+ }
680
+ }
681
+ continue;
682
+ }
683
+ if (t === "comment") {
684
+ const parsed = parseHashImport(node.text);
685
+ if (parsed) hashImports.push({ ...parsed, line: node.startPosition.row + 1 });
686
+ continue;
687
+ }
688
+ pushChildren(node, owner, sel, inExtension);
689
+ }
690
+ for (const ext of extensionSymbols) {
691
+ if (!declaredHere.has(ext.kindKey)) continue;
692
+ const sym = symbols[ext.index];
693
+ symbols.splice(ext.index, 1);
694
+ for (let i = extensionSymbols.length - 1; i >= 0; i--) {
695
+ if (extensionSymbols[i].index > ext.index) extensionSymbols[i].index--;
696
+ }
697
+ if (sym) sym.metadata = { ...sym.metadata, droppedExtensionSymbol: true };
698
+ }
699
+ for (const h of heritageEdges) {
700
+ if (h.owner === h.iface) continue;
701
+ const mine = memberNameNodes.get(h.owner);
702
+ const theirs = memberNameNodes.get(h.iface);
703
+ if (!mine || !theirs) continue;
704
+ for (const [member, nameNode] of mine) {
705
+ if (!theirs.has(member)) continue;
706
+ addRelationship(`${h.owner}.${member}`, `${h.iface}.${member}`, ASTEngine.RelationshipType.Override, this.lineOf(nameNode), "interface_member_supplied", {
707
+ implementedType: h.owner,
708
+ supertype: h.iface,
709
+ supertypeKind: h.ifaceKind ?? "undeclared_in_this_document",
710
+ member
711
+ });
712
+ }
713
+ }
714
+ if (hashImports.length > 0) {
715
+ const importer = lastPathSegment(filePath) || filePath;
716
+ for (const hi of hashImports) {
717
+ addRelationship(importer, hi.target, ASTEngine.RelationshipType.Imports, hi.line, "imports", {
718
+ isGraphqlImport: true,
719
+ importSource: importer,
720
+ importForm: hi.form,
721
+ // `fileLevel` IS THE FLAG THAT MAKES THE SOURCE ABOVE JOINABLE, and this edge was missing
722
+ // it while this analyzer's own `exports` edges already carried it. The M60/#910 contract
723
+ // (`parallel-indexer.ts:4391`) reads it as:
724
+ //
725
+ // if (!sourceSymbol && rel.metadata?.fileLevel === true) { … sourceExternal = relativePath }
726
+ //
727
+ // — a module-level edge whose source did not resolve to a symbol is rewritten to the
728
+ // IMPORTING FILE's project-relative path. Without the flag `source_external` keeps this
729
+ // analyzer's own spelling, a bare basename (`schema.graphql`), which no declaration can
730
+ // ever answer: the row existed, the dependency existed, and the only thing missing was who
731
+ // declared it — verbatim the defect that clause exists to fix, and the reason no surface
732
+ // could answer "what does this file include".
733
+ //
734
+ // NOTHING ABOVE IS DISCARDED: the store keeps this spelling in `metadata.scopeName`, and
735
+ // the fixture's assertion that the source IS the importing file's own name
736
+ // (`ontology-file-imports.expectation.json`) is about the analyzer's OUTPUT, which is
737
+ // unchanged. Metadata-only, so no target-side count can move — the residual probe's
738
+ // reproduction of the gate's TABLE 1, in the same run, is the independent check of that.
739
+ fileLevel: true,
740
+ // The bound names are real GraphQL identifiers in this document's scope; `[]`
741
+ // on a bare directive means "the document as a whole", which is not the same
742
+ // as "no names" and is distinguished by `importForm` rather than by omission.
743
+ ...hi.bindings.length > 0 ? { importBindings: hi.bindings } : {}
744
+ });
745
+ }
746
+ }
747
+ for (const s of symbols) {
748
+ if (s.metadata?.droppedExtensionSymbol) continue;
749
+ if (s.metadata?.topLevel !== true) continue;
750
+ exports.push({ name: s.name, kind: s.kind, range: s.range, visibility: "public" });
751
+ addRelationship("(file)", s.name, ASTEngine.RelationshipType.Exports, s.range.startLine, "exports", {
752
+ fileLevel: true,
753
+ ...s.metadata?.graphqlType ? { graphqlType: s.metadata.graphqlType } : {},
754
+ ...s.metadata?.graphqlCategory ? { graphqlCategory: s.metadata.graphqlCategory } : {}
755
+ });
756
+ }
757
+ const claimRoot = typeof context?.projectRoot === "string" && context.projectRoot.length > 0 ? context.projectRoot : null;
758
+ if (claimRoot !== null) {
759
+ for (const r of relationships) {
760
+ if (r.type !== ASTEngine.RelationshipType.Imports) continue;
761
+ const md = r.metadata;
762
+ if (!md || typeof md.importProjectFile === "string") continue;
763
+ const claim = fileClaimForTarget({
764
+ projectRoot: claimRoot,
765
+ filePath,
766
+ written: String(r.target ?? ""),
767
+ admittedExtensions: ["graphql", "gql"],
768
+ // THE POPULATION'S SIZE CAP, passed because this lane HAS over-cap files (4 for graphql,
769
+ // 2 for scss on the gate's own population line). A claim about one of them would be
770
+ // REFUTED, and nothing in the row would say why.
771
+ maxFileSizeBytes: FILE_CLAIM_MAX_BYTES
772
+ });
773
+ if (claim === null) continue;
774
+ md.importProjectFile = claim;
775
+ }
776
+ }
777
+ return {
778
+ language: "graphql",
779
+ symbols,
780
+ relationships,
781
+ imports,
782
+ exports,
783
+ errors,
784
+ metadata: {
785
+ complexity: symbols.length + relationships.length,
786
+ linesOfCode: content.split("\n").length,
787
+ patterns: [],
788
+ framework: "GraphQL",
789
+ hasFrameworkIntelligence: true,
790
+ hasTypeInference: true,
791
+ documentKind: this.documentKind(rootNode)
792
+ }
793
+ };
794
+ }
795
+ // ---------------------------------------------------------------- helpers
796
+ documentKind(rootNode) {
797
+ let hasTypeSystem = false;
798
+ let hasExecutable = false;
799
+ for (const def of this.topLevelDefinitions(rootNode)) {
800
+ const inner = this.innermostNamed(def);
801
+ if (!inner) continue;
802
+ if (this.typeOf(inner) === "OperationDefinition" || this.typeOf(inner) === "FragmentDefinition") hasExecutable = true;
803
+ else hasTypeSystem = true;
804
+ }
805
+ if (hasTypeSystem && hasExecutable) return "mixed";
806
+ if (hasTypeSystem) return "type_system";
807
+ if (hasExecutable) return "executable";
808
+ return "empty";
809
+ }
810
+ /**
811
+ * The document's top-level declarations: for each `Definition`, the innermost
812
+ * named child, which is the actual construct. Cheap (one level of the tree)
813
+ * and it is the only place a type can be DECLARED, so it is exactly the set
814
+ * an extension has to be compared against.
815
+ */
816
+ topLevelDeclarations(rootNode) {
817
+ const out = [];
818
+ for (const def of this.topLevelDefinitions(rootNode)) {
819
+ const inner = this.innermostNamed(def);
820
+ if (!inner) continue;
821
+ const typeNode = inner.type;
822
+ if (typeNode === "SchemaDefinition") {
823
+ out.push({ name: "schema", symbolKind: ASTEngine.SymbolKind.Namespace, typeNode });
824
+ continue;
825
+ }
826
+ if (typeNode === "DirectiveDefinition") {
827
+ const n2 = this.nameOf(inner);
828
+ if (n2) out.push({ name: `@${n2}`, symbolKind: ASTEngine.SymbolKind.Function, typeNode });
829
+ continue;
830
+ }
831
+ if (typeNode.endsWith("Extension")) continue;
832
+ const kind = this.definitionKindOf(typeNode);
833
+ if (!kind) continue;
834
+ const n = this.nameOf(inner);
835
+ if (n) out.push({ name: n, symbolKind: kind, typeNode });
836
+ }
837
+ return out;
838
+ }
839
+ /**
840
+ * The top-level type EXTENSIONS of a document, with the kind of the definition
841
+ * each one extends. Computed in the pre-pass, beside `topLevelDeclarations`,
842
+ * because both answers come from the same one-level walk and computing either
843
+ * on demand meant re-walking every definition per question.
844
+ */
845
+ topLevelExtensions(rootNode) {
846
+ const out = [];
847
+ for (const def of this.topLevelDefinitions(rootNode)) {
848
+ const inner = this.innermostNamed(def);
849
+ if (!inner || !inner.type.endsWith("Extension")) continue;
850
+ if (this.typeOf(inner) === "SchemaExtension") {
851
+ out.push({ name: "schema", symbolKind: ASTEngine.SymbolKind.Namespace });
852
+ continue;
853
+ }
854
+ const definitionType = EXTENSION_TO_DEFINITION[inner.type];
855
+ const kind = definitionType ? this.definitionKindOf(definitionType) : void 0;
856
+ const n = this.nameOf(inner);
857
+ if (kind && n) out.push({ name: n, symbolKind: kind });
858
+ }
859
+ return out;
860
+ }
861
+ definitionKindOf(typeNode) {
862
+ switch (typeNode) {
863
+ case "ObjectTypeDefinition":
864
+ case "InputObjectTypeDefinition":
865
+ return ASTEngine.SymbolKind.Class;
866
+ case "InterfaceTypeDefinition":
867
+ return ASTEngine.SymbolKind.Interface;
868
+ case "UnionTypeDefinition":
869
+ case "ScalarTypeDefinition":
870
+ return ASTEngine.SymbolKind.Type;
871
+ case "EnumTypeDefinition":
872
+ return ASTEngine.SymbolKind.Enum;
873
+ default:
874
+ return void 0;
875
+ }
876
+ }
877
+ /**
878
+ * The rule that classifies a top-level definition, reached by unwrapping the
879
+ * grammar's pass-through rules.
880
+ *
881
+ * The WRAPPER SET IS EXPLICIT. "Descend while there is exactly one named
882
+ * child" is not the same rule and is wrong: a shorthand operation is
883
+ * `Definition > ExecutableDefinition > OperationDefinition > SelectionSet >
884
+ * Selection > Field > Name`, and an unconditional descent returns `Name` — so
885
+ * `{ ping }` was classified as a type-system definition and every file's
886
+ * `documentKind` was wrong. A `schema` block hit the same descent
887
+ * (`… > SchemaDefinition > OperationTypeDefinition > NamedType > Name`).
888
+ */
889
+ static DEFINITION_WRAPPERS = /* @__PURE__ */ new Set([
890
+ "Document",
891
+ "Definition",
892
+ "ExecutableDefinition",
893
+ "TypeSystemDefinition",
894
+ "TypeSystemExtension",
895
+ "TypeDefinition",
896
+ "TypeExtension"
897
+ ]);
898
+ innermostNamed(node) {
899
+ let cur = node;
900
+ for (; ; ) {
901
+ if (!_RealGraphqlAnalyzer.DEFINITION_WRAPPERS.has(this.typeOf(cur))) return cur;
902
+ const next = this.onlyNamedChild(cur);
903
+ if (!next) return cur;
904
+ cur = next;
905
+ }
906
+ }
907
+ onlyNamedChild(node) {
908
+ if (!node) return null;
909
+ const kids = node.namedChildren;
910
+ if (kids.length !== 1) return null;
911
+ return kids[0];
912
+ }
913
+ /**
914
+ * The document's `Definition` children. The tree is
915
+ * `source_file > Document > Definition`, so the root is NOT the document —
916
+ * reading `Definition` straight off `source_file` finds nothing, which is how
917
+ * the extension de-duplication silently became a no-op and every
918
+ * `extend type X` in a file that also declared `X` published a SECOND `class
919
+ * X` (a duplicate identity in the index).
920
+ */
921
+ topLevelDefinitions(rootNode) {
922
+ if (this.typeOf(rootNode) === "Definition") return [rootNode];
923
+ if (this.typeOf(rootNode) === "Document") return this.childrenOfType(rootNode, "Definition");
924
+ const document = this.firstChildOfType(rootNode, "Document");
925
+ if (document) return this.childrenOfType(document, "Definition");
926
+ return this.childrenOfType(rootNode, "Definition");
927
+ }
928
+ childrenOfType(node, type) {
929
+ const out = [];
930
+ for (const c of node.namedChildren) {
931
+ if (c && this.typeOf(c) === type) out.push(c);
932
+ }
933
+ return out;
934
+ }
935
+ emitTypeSymbol(node, name, kind, typeNode, symbols, _relationships, _sel, _inExtension, directives) {
936
+ symbols.push({
937
+ name,
938
+ kind,
939
+ range: this.nodeToRange(node),
940
+ scope: "",
941
+ visibility: "public",
942
+ docstring: this.descriptionOf(node),
943
+ metadata: {
944
+ // `graphqlType` is the GRAMMAR's node type, on every branch of this
945
+ // analyzer, so a consumer can match on it; `graphqlCategory` is the
946
+ // specification's word for the same thing. They used to be one field
947
+ // with two possible vocabularies, which silently emptied `exports`.
948
+ graphqlType: typeNode,
949
+ topLevel: true,
950
+ graphqlCategory: typeNode === "UnionTypeDefinition" ? "union" : typeNode === "ScalarTypeDefinition" ? "scalar" : typeNode === "EnumTypeDefinition" ? "enum" : typeNode === "InputObjectTypeDefinition" ? "input" : typeNode === "InterfaceTypeDefinition" ? "interface" : "object",
951
+ ...this.directiveMetadata(directives)
952
+ }
953
+ });
954
+ }
955
+ /**
956
+ * A directive applied to a declaration is metadata ON that declaration, and —
957
+ * when the directive is defined in this file — a real reference to the
958
+ * `@directive` function symbol. Federation schemas (`@key(fields: "id")`,
959
+ * `@external`, `@requires`) carry their meaning almost entirely in these
960
+ * applications, so dropping them drops the schema's structure.
961
+ */
962
+ emitDirectiveApplications(_node, applications, owner, sel, addRelationship, inExtension) {
963
+ if (!owner || !applications) return;
964
+ for (const app of applications) {
965
+ addRelationship(owner, `@${app.name}`, ASTEngine.RelationshipType.Uses, app.line, "directive_application", {
966
+ ...app.arguments ? { arguments: app.arguments } : {},
967
+ ...sel.root && sel.root !== owner ? { within: sel.root } : {},
968
+ ...inExtension ? { extension: true } : {}
969
+ });
970
+ const dnode = DIRECTIVE_NODE.get(app);
971
+ const dargs = dnode ? this.firstChildOfType(dnode, "Arguments") : null;
972
+ if (dargs) {
973
+ for (const arg of this.childrenOfType(dargs, "Argument")) {
974
+ this.emitEnumValueReferences(owner, this.firstChildOfType(arg, "Value"), void 0, addRelationship, {
975
+ declaration: "directive_argument",
976
+ directive: `@${app.name}`
977
+ });
978
+ }
979
+ }
980
+ }
981
+ }
982
+ /**
983
+ * The `Directives` scan itself: the `Directives` child of a definition, as
984
+ * structured metadata. A directive argument is a CONSTANT in GraphQL (the
985
+ * specification forbids variables there), so the `Value` node's own text is the
986
+ * literal's exact source spelling — no unquoting, no guessing, no regular
987
+ * expression. Called ONCE per node; the walk memoises it in a WeakMap, because
988
+ * this scan is the analyzer's single most expensive operation.
989
+ */
990
+ scanDirectiveApplications(node) {
991
+ const directives = this.firstChildOfType(node, "Directives");
992
+ if (!directives) return null;
993
+ const list = [];
994
+ for (const d of this.childrenOfType(directives, "Directive")) {
995
+ const nameNode = this.firstChildOfType(d, "Name");
996
+ if (!nameNode) continue;
997
+ const argsNode = this.firstChildOfType(d, "Arguments");
998
+ const args = {};
999
+ if (argsNode) {
1000
+ for (const a of this.childrenOfType(argsNode, "Argument")) {
1001
+ const argName = this.nameOf(a);
1002
+ const value = this.firstChildOfType(a, "Value");
1003
+ if (argName && value) args[argName] = value.text;
1004
+ }
1005
+ }
1006
+ list.push({ name: nameNode.text, ...Object.keys(args).length ? { arguments: args } : {}, line: this.lineOf(nameNode) });
1007
+ DIRECTIVE_NODE.set(list[list.length - 1], d);
1008
+ }
1009
+ return list.length ? list : null;
1010
+ }
1011
+ /** The memoised scan's result, as symbol metadata; `{}` when there is none. */
1012
+ directiveMetadata(applications) {
1013
+ return applications ? { graphqlDirectives: applications } : _RealGraphqlAnalyzer.NO_DIRECTIVE_METADATA;
1014
+ }
1015
+ /** Frozen so a future in-place write fails loudly instead of corrupting every symbol. */
1016
+ static NO_DIRECTIVE_METADATA = Object.freeze({});
1017
+ /**
1018
+ * `on A | B | C` — the same left-recursion shape as `implements`, so the
1019
+ * locations are collected from the whole subtree, not from direct children.
1020
+ */
1021
+ collectDirectiveLocations(node) {
1022
+ const out = [];
1023
+ const stack = [node];
1024
+ while (stack.length) {
1025
+ const n = stack.pop();
1026
+ if (this.typeOf(n) === "DirectiveLocation") {
1027
+ const inner = this.findChild(n, (c) => this.typeOf(c) === "ExecutableDirectiveLocation" || this.typeOf(c) === "TypeSystemDirectiveLocation");
1028
+ const leaf = inner ? inner.namedChild(0) ?? inner : n;
1029
+ out.push({ name: leaf.text, node: leaf });
1030
+ continue;
1031
+ }
1032
+ const kids = n.namedChildren;
1033
+ for (let i = kids.length - 1; i >= 0; i--) {
1034
+ const c = kids[i];
1035
+ if (c) stack.push(c);
1036
+ }
1037
+ }
1038
+ return out;
1039
+ }
1040
+ /**
1041
+ * Every `NamedType` in a subtree, in source order and deduplicated.
1042
+ *
1043
+ * `ImplementsInterfaces` and `UnionMemberTypes` are left-recursive, so
1044
+ * `implements A & B & C` produces `I > I > I` in a tree-sitter build that
1045
+ * keeps the nesting, and a flat `I > [implements, A, &, B, &, C]` in one that
1046
+ * inlines the auxiliary repeat. Reading only DIRECT children — which is what
1047
+ * this analyzer used to do — therefore loses every implemented interface but
1048
+ * the last, and every union member but the last, on any grammar that nests.
1049
+ * Walking the subtree is correct for both shapes.
1050
+ */
1051
+ collectNamedTypes(node) {
1052
+ const out = [];
1053
+ const seen = /* @__PURE__ */ new Set();
1054
+ const stack = [node];
1055
+ while (stack.length) {
1056
+ const n = stack.pop();
1057
+ if (this.typeOf(n) === "NamedType") {
1058
+ const name = this.nameOf(n);
1059
+ if (name && !seen.has(name)) {
1060
+ seen.add(name);
1061
+ out.push({ name, node: n });
1062
+ }
1063
+ continue;
1064
+ }
1065
+ const kids = n.namedChildren;
1066
+ for (let i = kids.length - 1; i >= 0; i--) {
1067
+ const c = kids[i];
1068
+ if (c) stack.push(c);
1069
+ }
1070
+ }
1071
+ return out;
1072
+ }
1073
+ namedTypeNode(typeNode) {
1074
+ return this.findDescendant(typeNode, (n) => this.typeOf(n) === "NamedType");
1075
+ }
1076
+ /** Resolve a `Type`/`TypeCondition` node to its base named type name. */
1077
+ namedTypeName(typeNode) {
1078
+ const named = this.namedTypeNode(typeNode);
1079
+ return named ? this.nameOf(named) : void 0;
1080
+ }
1081
+ /**
1082
+ * Non-null-ness read off the grammar, not off the text. `typeNode.text`
1083
+ * containing `!` was the previous implementation; a type NAME may legally
1084
+ * contain `!` nowhere, but a future grammar could wrap the marker, and the
1085
+ * `NonNullType` node is the fact.
1086
+ */
1087
+ isNonNullType(typeNode) {
1088
+ const first = typeNode.namedChild(0);
1089
+ return first?.type === "NonNullType";
1090
+ }
1091
+ /** The `Value` of a `DefaultValue` child, as its exact source spelling. */
1092
+ defaultValueOf(node) {
1093
+ const dv = this.firstChildOfType(node, "DefaultValue");
1094
+ if (!dv) return void 0;
1095
+ const value = this.firstChildOfType(dv, "Value");
1096
+ return value?.text;
1097
+ }
1098
+ /**
1099
+ * Every `EnumValue` in a VALUE position — a reference — with its line.
1100
+ *
1101
+ * The grammar puts an `EnumValue` node in two different places, and conflating
1102
+ * them is the whole bug: `EnumValueDefinition > EnumValue` is a DECLARATION
1103
+ * (already a symbol, with a `contains` edge from its enum), while
1104
+ * `Value > EnumValue` is a REFERENCE to one. Only the second is a relationship,
1105
+ * and the test is the parent, never the node type alone. Values nest
1106
+ * (`ListValue > Value`, `ObjectField > Value`), so this descends rather than
1107
+ * looking at direct children.
1108
+ */
1109
+ enumValueReferences(valueNode) {
1110
+ const out = [];
1111
+ if (!valueNode) return out;
1112
+ const stack = [valueNode];
1113
+ while (stack.length) {
1114
+ const n = stack.pop();
1115
+ if (this.typeOf(n) === "EnumValue" && n.parent?.type === "Value") {
1116
+ const name = this.nameOf(n);
1117
+ if (name) out.push({ name, line: this.lineOf(n) });
1118
+ continue;
1119
+ }
1120
+ const kids = n.namedChildren;
1121
+ for (let i = kids.length - 1; i >= 0; i--) {
1122
+ const c = kids[i];
1123
+ if (c) stack.push(c);
1124
+ }
1125
+ }
1126
+ return out;
1127
+ }
1128
+ /**
1129
+ * Emit `uses` edges for the enum values a value position names.
1130
+ *
1131
+ * `enumType` is supplied ONLY where the document itself states which enum the
1132
+ * value belongs to — an `InputValueDefinition` or `VariableDefinition` carries
1133
+ * its own `Type` sibling, so `color: Color = RED` proves `RED` is `Color.RED`.
1134
+ * An executable field argument does not: `item(filter: { color: RED })` names
1135
+ * the INPUT OBJECT, and reaching `Color` would need that object's declaration,
1136
+ * which is in another file. So there the target stays the bare member name and
1137
+ * the store's own unique-name strategy decides it — the same rule the analyzer
1138
+ * already applies to a field selection.
1139
+ */
1140
+ emitEnumValueReferences(source, valueNode, enumType, addRelationship, metadata = {}) {
1141
+ if (!source) return;
1142
+ for (const ref of this.enumValueReferences(valueNode)) {
1143
+ const target = enumType ? `${enumType}.${ref.name}` : ref.name;
1144
+ addRelationship(source, target, ASTEngine.RelationshipType.Uses, ref.line, "enum_value_reference", { ...metadata, ...enumType ? { enumType } : {} });
1145
+ }
1146
+ }
1147
+ argumentNames(argsNode) {
1148
+ return this.childrenOfType(argsNode, "Argument").map((a) => this.nameOf(a)).filter((n) => !!n);
1149
+ }
1150
+ argumentPairs(argsNode) {
1151
+ const pairs = [];
1152
+ for (const arg of this.childrenOfType(argsNode, "InputValueDefinition")) {
1153
+ const typeNode = this.firstChildOfType(arg, "Type");
1154
+ pairs.push({
1155
+ name: this.nameOf(arg),
1156
+ type: typeNode ? this.namedTypeName(typeNode) : void 0,
1157
+ typeNode: typeNode ?? void 0,
1158
+ defaultNode: this.firstChildOfType(arg, "DefaultValue") ?? void 0
1159
+ });
1160
+ }
1161
+ return pairs;
1162
+ }
1163
+ /**
1164
+ * An argument's `isOptional` is GraphQL's own rule, not a guess from the
1165
+ * `!`: a NON-NULL argument is required; a NULLABLE argument is optional only
1166
+ * when it has a default. `f(x: Int)` is required, `f(x: Int = 1)` is not.
1167
+ */
1168
+ extractArguments(argsNode) {
1169
+ const params = [];
1170
+ for (const arg of this.childrenOfType(argsNode, "InputValueDefinition")) {
1171
+ const name = this.nameOf(arg);
1172
+ if (!name) continue;
1173
+ const typeNode = this.firstChildOfType(arg, "Type");
1174
+ const defaultValue = this.defaultValueOf(arg);
1175
+ params.push({
1176
+ name,
1177
+ type: typeNode ? this.namedTypeName(typeNode) : void 0,
1178
+ defaultValue,
1179
+ // GraphQL's own rule, from §3.6.1: an argument is OPTIONAL only when it
1180
+ // is NULLABLE **and** has a default. `f(a: Int)` is required even
1181
+ // though `Int` is nullable, because a caller must pass something;
1182
+ // `f(a: Int = 1)` is not. The previous implementation asked only
1183
+ // `!typeNode.text.includes("!")`, so it reported both nullable shapes
1184
+ // as optional and inverted the one distinction GraphQL makes.
1185
+ isOptional: typeNode ? !this.isNonNullType(typeNode) && defaultValue !== void 0 : true
1186
+ });
1187
+ }
1188
+ return params;
1189
+ }
1190
+ // ------------------------------------------------------------- descriptions
1191
+ /**
1192
+ * The description's VALUE, per specification §2.9.4.
1193
+ *
1194
+ * A `"…"` string is unquoted and its `EscapedCharacter` sequences are resolved
1195
+ * by an explicit character scan — `\" \\ \/ \b \f \n \r \t \uXXXX` and
1196
+ * `\\u{…}` — because the previous implementation returned the raw inner text
1197
+ * with the backslashes still in it, so `"a \"quote\""` was published as
1198
+ * `a \"quote\"`.
1199
+ *
1200
+ * A `"""…"""` block string is dedented as the specification defines: split on
1201
+ * line terminators, take the common indent of every line after the first that
1202
+ * has non-whitespace content, strip it, and drop leading and trailing blank
1203
+ * lines. Then `\"""` becomes `"""`.
1204
+ */
1205
+ descriptionOf(node) {
1206
+ const desc = this.firstChildOfType(node, "Description");
1207
+ if (!desc) return void 0;
1208
+ const sv = this.firstChildOfType(desc, "StringValue");
1209
+ if (!sv) return void 0;
1210
+ const raw = sv.text;
1211
+ if (raw.length >= 6 && raw.startsWith('"""') && raw.endsWith('"""')) {
1212
+ return this.blockStringValue(raw.slice(3, raw.length - 3));
1213
+ }
1214
+ if (raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"')) {
1215
+ return this.unescapeStringValue(raw.slice(1, raw.length - 1));
1216
+ }
1217
+ return raw;
1218
+ }
1219
+ /** §2.9.4 BlockStringValue: the common-indent algorithm, then the escape. */
1220
+ blockStringValue(inner) {
1221
+ const lines = inner.split("\n");
1222
+ let common;
1223
+ for (let i = 1; i < lines.length; i++) {
1224
+ const line = lines[i];
1225
+ let indent = 0;
1226
+ while (indent < line.length && (line[indent] === " " || line[indent] === " ")) indent++;
1227
+ if (indent === line.length) continue;
1228
+ common = common === void 0 ? indent : Math.min(common, indent);
1229
+ }
1230
+ if (common !== void 0 && common > 0) {
1231
+ for (let i = 1; i < lines.length; i++) lines[i] = lines[i].slice(common);
1232
+ }
1233
+ while (lines.length > 0 && lines[0].trim() === "") lines.shift();
1234
+ while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop();
1235
+ return lines.join("\n").replaceAll('\\"""', '"""');
1236
+ }
1237
+ /** §2.9.4 EscapedCharacter, resolved by scanning — no regular expression. */
1238
+ unescapeStringValue(inner) {
1239
+ let out = "";
1240
+ for (let i = 0; i < inner.length; i++) {
1241
+ const ch = inner[i];
1242
+ if (ch !== "\\") {
1243
+ out += ch;
1244
+ continue;
1245
+ }
1246
+ const next = inner[++i];
1247
+ switch (next) {
1248
+ case "b":
1249
+ out += "\b";
1250
+ break;
1251
+ case "f":
1252
+ out += "\f";
1253
+ break;
1254
+ case "n":
1255
+ out += "\n";
1256
+ break;
1257
+ case "r":
1258
+ out += "\r";
1259
+ break;
1260
+ case "t":
1261
+ out += " ";
1262
+ break;
1263
+ case "u": {
1264
+ if (inner[i + 1] === "{") {
1265
+ const close = inner.indexOf("}", i + 2);
1266
+ if (close > 0) {
1267
+ const code2 = Number.parseInt(inner.slice(i + 2, close), 16);
1268
+ if (Number.isFinite(code2) && code2 >= 0 && code2 <= 1114111) {
1269
+ out += String.fromCodePoint(code2);
1270
+ i = close;
1271
+ break;
1272
+ }
1273
+ }
1274
+ out += "\\u";
1275
+ break;
1276
+ }
1277
+ const hex = inner.slice(i + 1, i + 5);
1278
+ const code = Number.parseInt(hex, 16);
1279
+ if (hex.length === 4 && Number.isFinite(code)) {
1280
+ out += String.fromCharCode(code);
1281
+ i += 4;
1282
+ } else {
1283
+ out += "\\u";
1284
+ }
1285
+ break;
1286
+ }
1287
+ case void 0:
1288
+ out += "\\";
1289
+ break;
1290
+ default:
1291
+ out += next;
1292
+ break;
1293
+ }
1294
+ }
1295
+ return out;
1296
+ }
1297
+ // -------------------------------------------------------------------- ranges
1298
+ /**
1299
+ * 1-based line and column, byte offsets, and a leading `Description` skipped.
1300
+ *
1301
+ * The `Description` is a child of the definition node in this grammar, so a
1302
+ * naive `nodeToRange` reports the DOCSTRING's line for every described type,
1303
+ * field, argument, enum value and input field. On the GitHub public schema
1304
+ * that is 3,131 of 3,332 symbols — 94 % of the file's symbols pointing at a
1305
+ * line that does not contain the name they are named for. The M59/#861 rule
1306
+ * (a decorated declaration's line belongs to the name, not to its decorator)
1307
+ * is the same defect with a different decorator, and scala
1308
+ * (`declaration-lines-825`), typescript and javascript already implement it.
1309
+ */
1310
+ nodeToRange(node) {
1311
+ let anchor = node;
1312
+ const firstChild = node.child(0);
1313
+ if (firstChild && this.typeOf(firstChild) === "Description") {
1314
+ const afterDescription = node.child(1);
1315
+ if (afterDescription) anchor = afterDescription;
1316
+ }
1317
+ return {
1318
+ startLine: anchor.startPosition.row + 1,
1319
+ startColumn: anchor.startPosition.column + 1,
1320
+ endLine: node.endPosition.row + 1,
1321
+ endColumn: node.endPosition.column + 1,
1322
+ startIndex: anchor.startIndex,
1323
+ endIndex: node.endIndex
1324
+ };
1325
+ }
1326
+ lineOf(node) {
1327
+ return node ? node.startPosition.row + 1 : 0;
1328
+ }
1329
+ // ------------------------------------------------------------ node plumbing
1330
+ /** The definition's own name: its direct `Name` child, or a wrapper's. */
1331
+ nameOf(node) {
1332
+ return this.firstChildOfType(node, "Name")?.text;
1333
+ }
1334
+ /**
1335
+ * Is there a child matching `predicate`, ANONYMOUS children included?
1336
+ *
1337
+ * `findChild` walks `namedChild`, and `repeatable` is an anonymous keyword
1338
+ * token in this grammar, so `directive @a repeatable on FIELD` reported
1339
+ * `repeatable: false` — the specification's June-2018 feature was invisible
1340
+ * on every directive that used it.
1341
+ */
1342
+ hasChild(node, predicate) {
1343
+ for (let i = 0; i < node.childCount; i++) {
1344
+ const child = node.child(i);
1345
+ if (child && predicate(child)) return true;
1346
+ }
1347
+ return false;
1348
+ }
1349
+ isAnyOf(node, ...types) {
1350
+ return types.includes(this.typeOf(node));
1351
+ }
1352
+ /**
1353
+ * A node's NAMED children, in ONE wasm call.
1354
+ *
1355
+ * web-tree-sitter documents `namedChild(index)` as *"fairly fast, but its cost
1356
+ * is technically log(n), so if you might be iterating over a long list of
1357
+ * children, you should use Node#namedChildren instead"*, and that getter
1358
+ * materialises the whole list in a single call and CACHES it on the node. A
1359
+ * `namedChildCount` + `namedChild(i)` loop is therefore the O(n log n)
1360
+ * anti-pattern, and it was the one this analyzer used in nine places.
1361
+ *
1362
+ * The CPU profile of the 20,368-line GitHub public schema said so before this
1363
+ * change: the tree-sitter accessor layer — `setValue`, `getValue`,
1364
+ * `ts_node_named_child_wasm`, `ts_node_named_child_count_wasm`,
1365
+ * `get namedChildCount` — was over 11% of self time, and `pushChildren`, which
1366
+ * runs once per node, was its largest caller. The binding's own `children` /
1367
+ * `namedChildren` getters also replace a per-child `unmarshalNode` with one
1368
+ * bulk transfer, so this is fewer wasm round-trips as well as less arithmetic.
1369
+ *
1370
+ * The returned array is the BINDING'S OWN CACHE. It is read, never written.
1371
+ */
1372
+ namedChildrenOf(node) {
1373
+ return node.namedChildren;
1374
+ }
1375
+ /**
1376
+ * The first NAMED child of `type`, or null — with no closure and no per-index
1377
+ * wasm call.
1378
+ *
1379
+ * `findChild(node, n => this.typeOf(n) === "X")` is the idiomatic spelling and it was
1380
+ * used 40 times here, so it allocated 40 closures PER SYMBOL and reached `.type`
1381
+ * through a call frame for every child it examined. The comparison is a string
1382
+ * equality; the closure buys nothing. This is the same shape the SQL analyzer
1383
+ * uses for its own direct-child reads, and it is the shape the profile asked
1384
+ * for: `analyze` self time was 6.1% and the tree-sitter accessor layer was
1385
+ * another ~9%, and both are dominated by the NUMBER of property reads rather
1386
+ * than by any algorithm of ours.
1387
+ */
1388
+ firstChildOfType(node, type) {
1389
+ if (!node) return null;
1390
+ for (const child of node.namedChildren) {
1391
+ if (child !== null && this.typeOf(child) === type) return child;
1392
+ }
1393
+ return null;
1394
+ }
1395
+ findChild(node, predicate) {
1396
+ for (const child of node.namedChildren) {
1397
+ if (child && predicate(child)) return child;
1398
+ }
1399
+ return null;
1400
+ }
1401
+ /**
1402
+ * The first descendant satisfying `predicate`, in pre-order.
1403
+ *
1404
+ * ITERATIVE, and the recursion was a real defect rather than a style choice. This
1405
+ * walks to the depth of the subtree when the predicate does not match early, and
1406
+ * `[[[…[Int]]]]` is exactly that case: the `NamedType` sits at the BOTTOM, so the
1407
+ * recursion went as deep as the nesting. Measured, list nesting **2,749 deep
1408
+ * threw `RangeError: Maximum call stack size exceeded`**, and because the engine's
1409
+ * guard turns any throw into a minimal result, that file yielded ZERO symbols and
1410
+ * one opaque error — silently losing a whole type definition. The threshold is a
1411
+ * function of stack-frame size, so it is a platform figure, not a guarantee.
1412
+ *
1413
+ * `A & B & C` was never affected, which is why the bug survived the corpus: the
1414
+ * left-recursive rules put a `NamedType` at depth 1, so the predicate matched
1415
+ * immediately and the recursion never went deep. 5,000 clauses still work.
1416
+ *
1417
+ * Children are pushed in reverse so they POP in order, which keeps this a
1418
+ * pre-order DFS with first-match-wins — the same order, and the same result, as
1419
+ * the recursion it replaces.
1420
+ */
1421
+ findDescendant(node, predicate) {
1422
+ const stack = [];
1423
+ const rootKids = node.namedChildren;
1424
+ for (let i = rootKids.length - 1; i >= 0; i--) {
1425
+ const c = rootKids[i];
1426
+ if (c) stack.push(c);
1427
+ }
1428
+ while (stack.length) {
1429
+ const n = stack.pop();
1430
+ if (predicate(n)) return n;
1431
+ const kids = n.namedChildren;
1432
+ for (let i = kids.length - 1; i >= 0; i--) {
1433
+ const c = kids[i];
1434
+ if (c) stack.push(c);
1435
+ }
1436
+ }
1437
+ return null;
1438
+ }
1439
+ };
1440
+ export {
1441
+ RealGraphqlAnalyzer
1442
+ };