cgraphx 2.0.2 → 2.0.3

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 (680) hide show
  1. package/dist/core/code/engine/cli/analyze-config.js +320 -0
  2. package/dist/core/code/engine/cli/analyze.js +1086 -0
  3. package/dist/core/code/engine/cli/cli-message.js +83 -0
  4. package/dist/core/code/engine/cli/detect-changes-format.js +58 -0
  5. package/dist/core/code/engine/cli/embedding-dims.js +43 -0
  6. package/dist/core/code/engine/cli/format-elapsed.js +12 -0
  7. package/dist/core/code/engine/cli/help-i18n.js +144 -0
  8. package/dist/core/code/engine/cli/i18n/en.js +110 -0
  9. package/dist/core/code/engine/cli/i18n/index.js +47 -0
  10. package/dist/core/code/engine/cli/i18n/resources.js +9 -0
  11. package/dist/core/code/engine/cli/i18n/zh-CN.js +110 -0
  12. package/dist/core/code/engine/cli/lazy-action.js +67 -0
  13. package/dist/core/code/engine/cli/optional-grammars.js +136 -0
  14. package/dist/core/code/engine/cli/resolve-invocation.js +76 -0
  15. package/dist/core/code/engine/cli/status.js +156 -0
  16. package/dist/core/code/engine/cli/tool.js +384 -0
  17. package/dist/core/code/engine/config/ignore-service.js +511 -0
  18. package/dist/core/code/engine/config/supported-languages.js +17 -0
  19. package/dist/core/code/engine/core/analysis-features.js +64 -0
  20. package/dist/core/code/engine/core/analyzer-identity.js +2171 -0
  21. package/dist/core/code/engine/core/git-staleness.js +180 -0
  22. package/dist/core/code/engine/core/graph/graph.js +180 -0
  23. package/dist/core/code/engine/core/graph/import-cycles.js +106 -0
  24. package/dist/core/code/engine/core/graph/types.js +2 -0
  25. package/dist/core/code/engine/core/index-freshness.js +12 -0
  26. package/dist/core/code/engine/core/ingestion/binding-accumulator.js +341 -0
  27. package/dist/core/code/engine/core/ingestion/call-extractors/configs/c-cpp.js +168 -0
  28. package/dist/core/code/engine/core/ingestion/call-extractors/configs/csharp.js +9 -0
  29. package/dist/core/code/engine/core/ingestion/call-extractors/configs/dart.js +8 -0
  30. package/dist/core/code/engine/core/ingestion/call-extractors/configs/go.js +8 -0
  31. package/dist/core/code/engine/core/ingestion/call-extractors/configs/jvm.js +54 -0
  32. package/dist/core/code/engine/core/ingestion/call-extractors/configs/php.js +8 -0
  33. package/dist/core/code/engine/core/ingestion/call-extractors/configs/python.js +8 -0
  34. package/dist/core/code/engine/core/ingestion/call-extractors/configs/ruby.js +8 -0
  35. package/dist/core/code/engine/core/ingestion/call-extractors/configs/rust.js +8 -0
  36. package/dist/core/code/engine/core/ingestion/call-extractors/configs/swift.js +8 -0
  37. package/dist/core/code/engine/core/ingestion/call-extractors/configs/typescript-javascript.js +11 -0
  38. package/dist/core/code/engine/core/ingestion/call-extractors/generic.js +62 -0
  39. package/dist/core/code/engine/core/ingestion/call-processor.js +503 -0
  40. package/dist/core/code/engine/core/ingestion/call-routing.js +98 -0
  41. package/dist/core/code/engine/core/ingestion/call-types.js +3 -0
  42. package/dist/core/code/engine/core/ingestion/cfg/callee-cell-format.js +45 -0
  43. package/dist/core/code/engine/core/ingestion/cfg/cfg-builder.js +202 -0
  44. package/dist/core/code/engine/core/ingestion/cfg/collect.js +81 -0
  45. package/dist/core/code/engine/core/ingestion/cfg/control-dependence.js +185 -0
  46. package/dist/core/code/engine/core/ingestion/cfg/control-flow-context.js +130 -0
  47. package/dist/core/code/engine/core/ingestion/cfg/emit.js +646 -0
  48. package/dist/core/code/engine/core/ingestion/cfg/post-dominators.js +182 -0
  49. package/dist/core/code/engine/core/ingestion/cfg/reaching-def-reason-codec.js +139 -0
  50. package/dist/core/code/engine/core/ingestion/cfg/reaching-defs-graph.js +322 -0
  51. package/dist/core/code/engine/core/ingestion/cfg/reaching-defs.js +792 -0
  52. package/dist/core/code/engine/core/ingestion/cfg/synthetic-escape.js +305 -0
  53. package/dist/core/code/engine/core/ingestion/cfg/traversal-result.js +6 -0
  54. package/dist/core/code/engine/core/ingestion/cfg/types.js +14 -0
  55. package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp-harvest.js +545 -0
  56. package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp.js +590 -0
  57. package/dist/core/code/engine/core/ingestion/cfg/visitors/call-site-harvest.js +356 -0
  58. package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp-harvest.js +593 -0
  59. package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp.js +871 -0
  60. package/dist/core/code/engine/core/ingestion/cfg/visitors/dart-harvest.js +874 -0
  61. package/dist/core/code/engine/core/ingestion/cfg/visitors/dart.js +840 -0
  62. package/dist/core/code/engine/core/ingestion/cfg/visitors/go-harvest.js +625 -0
  63. package/dist/core/code/engine/core/ingestion/cfg/visitors/go.js +642 -0
  64. package/dist/core/code/engine/core/ingestion/cfg/visitors/java-harvest.js +517 -0
  65. package/dist/core/code/engine/core/ingestion/cfg/visitors/java.js +816 -0
  66. package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin-harvest.js +723 -0
  67. package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin.js +813 -0
  68. package/dist/core/code/engine/core/ingestion/cfg/visitors/php-harvest.js +630 -0
  69. package/dist/core/code/engine/core/ingestion/cfg/visitors/php.js +725 -0
  70. package/dist/core/code/engine/core/ingestion/cfg/visitors/python-harvest.js +776 -0
  71. package/dist/core/code/engine/core/ingestion/cfg/visitors/python.js +562 -0
  72. package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby-harvest.js +591 -0
  73. package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby.js +760 -0
  74. package/dist/core/code/engine/core/ingestion/cfg/visitors/rust-harvest.js +877 -0
  75. package/dist/core/code/engine/core/ingestion/cfg/visitors/rust.js +562 -0
  76. package/dist/core/code/engine/core/ingestion/cfg/visitors/scope-tree-harvest.js +120 -0
  77. package/dist/core/code/engine/core/ingestion/cfg/visitors/swift-harvest.js +683 -0
  78. package/dist/core/code/engine/core/ingestion/cfg/visitors/swift.js +791 -0
  79. package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript-harvest.js +1060 -0
  80. package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript.js +587 -0
  81. package/dist/core/code/engine/core/ingestion/class-extractors/configs/c-cpp.js +77 -0
  82. package/dist/core/code/engine/core/ingestion/class-extractors/configs/csharp.js +24 -0
  83. package/dist/core/code/engine/core/ingestion/class-extractors/configs/dart.js +10 -0
  84. package/dist/core/code/engine/core/ingestion/class-extractors/configs/go.js +28 -0
  85. package/dist/core/code/engine/core/ingestion/class-extractors/configs/jvm.js +67 -0
  86. package/dist/core/code/engine/core/ingestion/class-extractors/configs/php.js +10 -0
  87. package/dist/core/code/engine/core/ingestion/class-extractors/configs/python.js +10 -0
  88. package/dist/core/code/engine/core/ingestion/class-extractors/configs/ruby.js +13 -0
  89. package/dist/core/code/engine/core/ingestion/class-extractors/configs/rust.js +10 -0
  90. package/dist/core/code/engine/core/ingestion/class-extractors/configs/swift.js +21 -0
  91. package/dist/core/code/engine/core/ingestion/class-extractors/configs/typescript-javascript.js +31 -0
  92. package/dist/core/code/engine/core/ingestion/class-extractors/generic.js +144 -0
  93. package/dist/core/code/engine/core/ingestion/class-types.js +2 -0
  94. package/dist/core/code/engine/core/ingestion/cluster-enricher.js +174 -0
  95. package/dist/core/code/engine/core/ingestion/community-processor.js +604 -0
  96. package/dist/core/code/engine/core/ingestion/constants.js +26 -0
  97. package/dist/core/code/engine/core/ingestion/cpp-ue-preprocessor.js +263 -0
  98. package/dist/core/code/engine/core/ingestion/csharp-namespace-gate.js +133 -0
  99. package/dist/core/code/engine/core/ingestion/di-extractors/index.js +38 -0
  100. package/dist/core/code/engine/core/ingestion/di-extractors/spring.js +310 -0
  101. package/dist/core/code/engine/core/ingestion/emit-references.js +244 -0
  102. package/dist/core/code/engine/core/ingestion/entry-point-scoring.js +201 -0
  103. package/dist/core/code/engine/core/ingestion/export-detection.js +244 -0
  104. package/dist/core/code/engine/core/ingestion/field-extractor.js +29 -0
  105. package/dist/core/code/engine/core/ingestion/field-extractors/configs/c-cpp.js +107 -0
  106. package/dist/core/code/engine/core/ingestion/field-extractors/configs/csharp.js +124 -0
  107. package/dist/core/code/engine/core/ingestion/field-extractors/configs/dart.js +99 -0
  108. package/dist/core/code/engine/core/ingestion/field-extractors/configs/go.js +102 -0
  109. package/dist/core/code/engine/core/ingestion/field-extractors/configs/helpers.js +198 -0
  110. package/dist/core/code/engine/core/ingestion/field-extractors/configs/jvm.js +172 -0
  111. package/dist/core/code/engine/core/ingestion/field-extractors/configs/php.js +67 -0
  112. package/dist/core/code/engine/core/ingestion/field-extractors/configs/python.js +94 -0
  113. package/dist/core/code/engine/core/ingestion/field-extractors/configs/ruby.js +79 -0
  114. package/dist/core/code/engine/core/ingestion/field-extractors/configs/rust.js +55 -0
  115. package/dist/core/code/engine/core/ingestion/field-extractors/configs/swift.js +93 -0
  116. package/dist/core/code/engine/core/ingestion/field-extractors/configs/typescript-javascript.js +59 -0
  117. package/dist/core/code/engine/core/ingestion/field-extractors/generic.js +147 -0
  118. package/dist/core/code/engine/core/ingestion/field-extractors/typescript.js +266 -0
  119. package/dist/core/code/engine/core/ingestion/field-types.js +3 -0
  120. package/dist/core/code/engine/core/ingestion/filesystem-walker.js +136 -0
  121. package/dist/core/code/engine/core/ingestion/finalize-orchestrator.js +159 -0
  122. package/dist/core/code/engine/core/ingestion/framework-detection.js +432 -0
  123. package/dist/core/code/engine/core/ingestion/frameworks/spring/analysis-features.js +38 -0
  124. package/dist/core/code/engine/core/ingestion/frameworks/spring/annotation-arguments.js +234 -0
  125. package/dist/core/code/engine/core/ingestion/frameworks/spring/aop-candidates.js +88 -0
  126. package/dist/core/code/engine/core/ingestion/frameworks/spring/aop.js +487 -0
  127. package/dist/core/code/engine/core/ingestion/frameworks/spring/auto-configuration.js +21 -0
  128. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-candidates.js +189 -0
  129. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-catalog.js +32 -0
  130. package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-factories.js +73 -0
  131. package/dist/core/code/engine/core/ingestion/frameworks/spring/conditionals.js +323 -0
  132. package/dist/core/code/engine/core/ingestion/frameworks/spring/config-bindings.js +119 -0
  133. package/dist/core/code/engine/core/ingestion/frameworks/spring/di-metadata.js +385 -0
  134. package/dist/core/code/engine/core/ingestion/frameworks/spring/resource-injection.js +96 -0
  135. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/c-cpp.js +17 -0
  136. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/csharp.js +46 -0
  137. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/dart.js +59 -0
  138. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/go.js +30 -0
  139. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/jvm.js +73 -0
  140. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/php.js +19 -0
  141. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/python.js +45 -0
  142. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/ruby.js +20 -0
  143. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/rust.js +58 -0
  144. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/swift.js +94 -0
  145. package/dist/core/code/engine/core/ingestion/import-resolvers/configs/typescript-javascript.js +26 -0
  146. package/dist/core/code/engine/core/ingestion/import-resolvers/csharp.js +128 -0
  147. package/dist/core/code/engine/core/ingestion/import-resolvers/go.js +50 -0
  148. package/dist/core/code/engine/core/ingestion/import-resolvers/jvm.js +112 -0
  149. package/dist/core/code/engine/core/ingestion/import-resolvers/php.js +80 -0
  150. package/dist/core/code/engine/core/ingestion/import-resolvers/python.js +75 -0
  151. package/dist/core/code/engine/core/ingestion/import-resolvers/resolver-factory.js +36 -0
  152. package/dist/core/code/engine/core/ingestion/import-resolvers/ruby.js +20 -0
  153. package/dist/core/code/engine/core/ingestion/import-resolvers/rust.js +79 -0
  154. package/dist/core/code/engine/core/ingestion/import-resolvers/standard.js +180 -0
  155. package/dist/core/code/engine/core/ingestion/import-resolvers/types.js +7 -0
  156. package/dist/core/code/engine/core/ingestion/import-resolvers/utils.js +153 -0
  157. package/dist/core/code/engine/core/ingestion/import-target-adapter.js +99 -0
  158. package/dist/core/code/engine/core/ingestion/language-config.js +391 -0
  159. package/dist/core/code/engine/core/ingestion/language-provider.js +25 -0
  160. package/dist/core/code/engine/core/ingestion/languages/c/arity-metadata.js +98 -0
  161. package/dist/core/code/engine/core/ingestion/languages/c/arity.js +21 -0
  162. package/dist/core/code/engine/core/ingestion/languages/c/capture-side-channel.js +69 -0
  163. package/dist/core/code/engine/core/ingestion/languages/c/captures.js +189 -0
  164. package/dist/core/code/engine/core/ingestion/languages/c/header-scan.js +58 -0
  165. package/dist/core/code/engine/core/ingestion/languages/c/import-decomposer.js +68 -0
  166. package/dist/core/code/engine/core/ingestion/languages/c/import-target.js +103 -0
  167. package/dist/core/code/engine/core/ingestion/languages/c/index.js +33 -0
  168. package/dist/core/code/engine/core/ingestion/languages/c/interpret.js +53 -0
  169. package/dist/core/code/engine/core/ingestion/languages/c/merge-bindings.js +26 -0
  170. package/dist/core/code/engine/core/ingestion/languages/c/query.js +210 -0
  171. package/dist/core/code/engine/core/ingestion/languages/c/scope-resolver.js +112 -0
  172. package/dist/core/code/engine/core/ingestion/languages/c/simple-hooks.js +24 -0
  173. package/dist/core/code/engine/core/ingestion/languages/c/static-linkage.js +109 -0
  174. package/dist/core/code/engine/core/ingestion/languages/c-cpp.js +506 -0
  175. package/dist/core/code/engine/core/ingestion/languages/cpp/adl.js +804 -0
  176. package/dist/core/code/engine/core/ingestion/languages/cpp/arity-metadata.js +258 -0
  177. package/dist/core/code/engine/core/ingestion/languages/cpp/arity.js +37 -0
  178. package/dist/core/code/engine/core/ingestion/languages/cpp/capture-side-channel.js +89 -0
  179. package/dist/core/code/engine/core/ingestion/languages/cpp/captures.js +1975 -0
  180. package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-extractor.js +311 -0
  181. package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-filter.js +210 -0
  182. package/dist/core/code/engine/core/ingestion/languages/cpp/conversion-rank.js +163 -0
  183. package/dist/core/code/engine/core/ingestion/languages/cpp/file-local-linkage.js +327 -0
  184. package/dist/core/code/engine/core/ingestion/languages/cpp/header-scan.js +53 -0
  185. package/dist/core/code/engine/core/ingestion/languages/cpp/import-decomposer.js +134 -0
  186. package/dist/core/code/engine/core/ingestion/languages/cpp/import-target.js +16 -0
  187. package/dist/core/code/engine/core/ingestion/languages/cpp/index.js +33 -0
  188. package/dist/core/code/engine/core/ingestion/languages/cpp/inline-namespaces.js +379 -0
  189. package/dist/core/code/engine/core/ingestion/languages/cpp/interpret.js +239 -0
  190. package/dist/core/code/engine/core/ingestion/languages/cpp/member-lookup.js +470 -0
  191. package/dist/core/code/engine/core/ingestion/languages/cpp/merge-bindings.js +32 -0
  192. package/dist/core/code/engine/core/ingestion/languages/cpp/query.js +763 -0
  193. package/dist/core/code/engine/core/ingestion/languages/cpp/range-bindings.js +230 -0
  194. package/dist/core/code/engine/core/ingestion/languages/cpp/scope-resolver.js +354 -0
  195. package/dist/core/code/engine/core/ingestion/languages/cpp/simple-hooks.js +67 -0
  196. package/dist/core/code/engine/core/ingestion/languages/cpp/two-phase-lookup.js +348 -0
  197. package/dist/core/code/engine/core/ingestion/languages/cpp/type-classifier.js +56 -0
  198. package/dist/core/code/engine/core/ingestion/languages/cpp/user-defined-conversions.js +128 -0
  199. package/dist/core/code/engine/core/ingestion/languages/csharp/accessor-unwrap.js +67 -0
  200. package/dist/core/code/engine/core/ingestion/languages/csharp/arity-metadata.js +49 -0
  201. package/dist/core/code/engine/core/ingestion/languages/csharp/arity.js +40 -0
  202. package/dist/core/code/engine/core/ingestion/languages/csharp/cache-stats.js +32 -0
  203. package/dist/core/code/engine/core/ingestion/languages/csharp/captures.js +557 -0
  204. package/dist/core/code/engine/core/ingestion/languages/csharp/import-decomposer.js +96 -0
  205. package/dist/core/code/engine/core/ingestion/languages/csharp/import-target.js +176 -0
  206. package/dist/core/code/engine/core/ingestion/languages/csharp/index.js +95 -0
  207. package/dist/core/code/engine/core/ingestion/languages/csharp/interpret.js +150 -0
  208. package/dist/core/code/engine/core/ingestion/languages/csharp/merge-bindings.js +58 -0
  209. package/dist/core/code/engine/core/ingestion/languages/csharp/namespace-siblings.js +708 -0
  210. package/dist/core/code/engine/core/ingestion/languages/csharp/qualified-type-names.js +62 -0
  211. package/dist/core/code/engine/core/ingestion/languages/csharp/query.js +578 -0
  212. package/dist/core/code/engine/core/ingestion/languages/csharp/receiver-binding.js +142 -0
  213. package/dist/core/code/engine/core/ingestion/languages/csharp/resolution-config.js +18 -0
  214. package/dist/core/code/engine/core/ingestion/languages/csharp/scope-resolver.js +84 -0
  215. package/dist/core/code/engine/core/ingestion/languages/csharp/simple-hooks.js +81 -0
  216. package/dist/core/code/engine/core/ingestion/languages/csharp.js +204 -0
  217. package/dist/core/code/engine/core/ingestion/languages/dart/arity-metadata.js +38 -0
  218. package/dist/core/code/engine/core/ingestion/languages/dart/arity.js +34 -0
  219. package/dist/core/code/engine/core/ingestion/languages/dart/built-ins.js +37 -0
  220. package/dist/core/code/engine/core/ingestion/languages/dart/cache-stats.js +30 -0
  221. package/dist/core/code/engine/core/ingestion/languages/dart/captures.js +1096 -0
  222. package/dist/core/code/engine/core/ingestion/languages/dart/expand-wildcards.js +34 -0
  223. package/dist/core/code/engine/core/ingestion/languages/dart/extension-type-preprocess.js +33 -0
  224. package/dist/core/code/engine/core/ingestion/languages/dart/import-target.js +68 -0
  225. package/dist/core/code/engine/core/ingestion/languages/dart/index.js +45 -0
  226. package/dist/core/code/engine/core/ingestion/languages/dart/interpret.js +101 -0
  227. package/dist/core/code/engine/core/ingestion/languages/dart/merge-bindings.js +42 -0
  228. package/dist/core/code/engine/core/ingestion/languages/dart/query.js +246 -0
  229. package/dist/core/code/engine/core/ingestion/languages/dart/receiver-binding.js +90 -0
  230. package/dist/core/code/engine/core/ingestion/languages/dart/scope-resolver.js +197 -0
  231. package/dist/core/code/engine/core/ingestion/languages/dart/signature-bindings.js +54 -0
  232. package/dist/core/code/engine/core/ingestion/languages/dart/simple-hooks.js +61 -0
  233. package/dist/core/code/engine/core/ingestion/languages/dart.js +138 -0
  234. package/dist/core/code/engine/core/ingestion/languages/go/arity-metadata.js +71 -0
  235. package/dist/core/code/engine/core/ingestion/languages/go/arity.js +17 -0
  236. package/dist/core/code/engine/core/ingestion/languages/go/cache-stats.js +21 -0
  237. package/dist/core/code/engine/core/ingestion/languages/go/captures.js +492 -0
  238. package/dist/core/code/engine/core/ingestion/languages/go/expand-wildcards.js +97 -0
  239. package/dist/core/code/engine/core/ingestion/languages/go/generic-type-parameters.js +146 -0
  240. package/dist/core/code/engine/core/ingestion/languages/go/import-decomposer.js +47 -0
  241. package/dist/core/code/engine/core/ingestion/languages/go/import-target.js +70 -0
  242. package/dist/core/code/engine/core/ingestion/languages/go/index.js +39 -0
  243. package/dist/core/code/engine/core/ingestion/languages/go/interface-impls.js +955 -0
  244. package/dist/core/code/engine/core/ingestion/languages/go/interpret.js +177 -0
  245. package/dist/core/code/engine/core/ingestion/languages/go/merge-bindings.js +21 -0
  246. package/dist/core/code/engine/core/ingestion/languages/go/method-owners.js +131 -0
  247. package/dist/core/code/engine/core/ingestion/languages/go/namespace-mirror.js +56 -0
  248. package/dist/core/code/engine/core/ingestion/languages/go/package-clause.js +79 -0
  249. package/dist/core/code/engine/core/ingestion/languages/go/package-siblings.js +83 -0
  250. package/dist/core/code/engine/core/ingestion/languages/go/query.js +298 -0
  251. package/dist/core/code/engine/core/ingestion/languages/go/range-binding.js +127 -0
  252. package/dist/core/code/engine/core/ingestion/languages/go/receiver-binding.js +24 -0
  253. package/dist/core/code/engine/core/ingestion/languages/go/scope-resolver.js +75 -0
  254. package/dist/core/code/engine/core/ingestion/languages/go/simple-hooks.js +31 -0
  255. package/dist/core/code/engine/core/ingestion/languages/go/type-binding.js +279 -0
  256. package/dist/core/code/engine/core/ingestion/languages/go.js +160 -0
  257. package/dist/core/code/engine/core/ingestion/languages/index.js +66 -0
  258. package/dist/core/code/engine/core/ingestion/languages/java/analysis-features.js +16 -0
  259. package/dist/core/code/engine/core/ingestion/languages/java/arity-metadata.js +43 -0
  260. package/dist/core/code/engine/core/ingestion/languages/java/arity.js +27 -0
  261. package/dist/core/code/engine/core/ingestion/languages/java/cache-stats.js +32 -0
  262. package/dist/core/code/engine/core/ingestion/languages/java/capture-side-channel.js +123 -0
  263. package/dist/core/code/engine/core/ingestion/languages/java/captures.js +791 -0
  264. package/dist/core/code/engine/core/ingestion/languages/java/import-decomposer.js +88 -0
  265. package/dist/core/code/engine/core/ingestion/languages/java/import-target.js +103 -0
  266. package/dist/core/code/engine/core/ingestion/languages/java/index.js +43 -0
  267. package/dist/core/code/engine/core/ingestion/languages/java/interpret.js +146 -0
  268. package/dist/core/code/engine/core/ingestion/languages/java/merge-bindings.js +43 -0
  269. package/dist/core/code/engine/core/ingestion/languages/java/package-facts.js +16 -0
  270. package/dist/core/code/engine/core/ingestion/languages/java/package-siblings.js +11 -0
  271. package/dist/core/code/engine/core/ingestion/languages/java/query.js +319 -0
  272. package/dist/core/code/engine/core/ingestion/languages/java/receiver-binding.js +98 -0
  273. package/dist/core/code/engine/core/ingestion/languages/java/scope-resolver.js +213 -0
  274. package/dist/core/code/engine/core/ingestion/languages/java/simple-hooks.js +39 -0
  275. package/dist/core/code/engine/core/ingestion/languages/java/spring-aop.js +53 -0
  276. package/dist/core/code/engine/core/ingestion/languages/java/spring-bean-metadata.js +11 -0
  277. package/dist/core/code/engine/core/ingestion/languages/java/spring-conditionals.js +52 -0
  278. package/dist/core/code/engine/core/ingestion/languages/java/spring-config-bindings.js +222 -0
  279. package/dist/core/code/engine/core/ingestion/languages/java/spring-di.js +165 -0
  280. package/dist/core/code/engine/core/ingestion/languages/java.js +192 -0
  281. package/dist/core/code/engine/core/ingestion/languages/javascript/arity.js +15 -0
  282. package/dist/core/code/engine/core/ingestion/languages/javascript/captures.js +1122 -0
  283. package/dist/core/code/engine/core/ingestion/languages/javascript/import-target.js +56 -0
  284. package/dist/core/code/engine/core/ingestion/languages/javascript/index.js +109 -0
  285. package/dist/core/code/engine/core/ingestion/languages/javascript/interpret.js +45 -0
  286. package/dist/core/code/engine/core/ingestion/languages/javascript/merge-bindings.js +21 -0
  287. package/dist/core/code/engine/core/ingestion/languages/javascript/query.js +659 -0
  288. package/dist/core/code/engine/core/ingestion/languages/javascript/scope-resolver.js +78 -0
  289. package/dist/core/code/engine/core/ingestion/languages/javascript/simple-hooks.js +44 -0
  290. package/dist/core/code/engine/core/ingestion/languages/jvm/package-facts.js +46 -0
  291. package/dist/core/code/engine/core/ingestion/languages/jvm/package-siblings.js +200 -0
  292. package/dist/core/code/engine/core/ingestion/languages/kotlin/arity-metadata.js +23 -0
  293. package/dist/core/code/engine/core/ingestion/languages/kotlin/arity.js +18 -0
  294. package/dist/core/code/engine/core/ingestion/languages/kotlin/cache-stats.js +21 -0
  295. package/dist/core/code/engine/core/ingestion/languages/kotlin/capture-side-channel.js +160 -0
  296. package/dist/core/code/engine/core/ingestion/languages/kotlin/captures.js +1262 -0
  297. package/dist/core/code/engine/core/ingestion/languages/kotlin/companion-scopes.js +72 -0
  298. package/dist/core/code/engine/core/ingestion/languages/kotlin/import-decomposer.js +40 -0
  299. package/dist/core/code/engine/core/ingestion/languages/kotlin/import-target.js +135 -0
  300. package/dist/core/code/engine/core/ingestion/languages/kotlin/index.js +26 -0
  301. package/dist/core/code/engine/core/ingestion/languages/kotlin/interpret.js +75 -0
  302. package/dist/core/code/engine/core/ingestion/languages/kotlin/merge-bindings.js +28 -0
  303. package/dist/core/code/engine/core/ingestion/languages/kotlin/owners.js +134 -0
  304. package/dist/core/code/engine/core/ingestion/languages/kotlin/package-facts.js +16 -0
  305. package/dist/core/code/engine/core/ingestion/languages/kotlin/package-siblings.js +11 -0
  306. package/dist/core/code/engine/core/ingestion/languages/kotlin/query.js +243 -0
  307. package/dist/core/code/engine/core/ingestion/languages/kotlin/receiver-binding.js +103 -0
  308. package/dist/core/code/engine/core/ingestion/languages/kotlin/scope-resolver.js +207 -0
  309. package/dist/core/code/engine/core/ingestion/languages/kotlin/simple-hooks.js +42 -0
  310. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-aop.js +68 -0
  311. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-bean-metadata.js +11 -0
  312. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-conditionals.js +53 -0
  313. package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-di.js +304 -0
  314. package/dist/core/code/engine/core/ingestion/languages/kotlin.js +189 -0
  315. package/dist/core/code/engine/core/ingestion/languages/php/arity-metadata.js +66 -0
  316. package/dist/core/code/engine/core/ingestion/languages/php/arity.js +43 -0
  317. package/dist/core/code/engine/core/ingestion/languages/php/cache-stats.js +32 -0
  318. package/dist/core/code/engine/core/ingestion/languages/php/captures.js +1166 -0
  319. package/dist/core/code/engine/core/ingestion/languages/php/import-decomposer.js +238 -0
  320. package/dist/core/code/engine/core/ingestion/languages/php/import-target.js +213 -0
  321. package/dist/core/code/engine/core/ingestion/languages/php/index.js +85 -0
  322. package/dist/core/code/engine/core/ingestion/languages/php/interpret.js +256 -0
  323. package/dist/core/code/engine/core/ingestion/languages/php/merge-bindings.js +50 -0
  324. package/dist/core/code/engine/core/ingestion/languages/php/namespace-siblings.js +353 -0
  325. package/dist/core/code/engine/core/ingestion/languages/php/query.js +391 -0
  326. package/dist/core/code/engine/core/ingestion/languages/php/receiver-binding.js +135 -0
  327. package/dist/core/code/engine/core/ingestion/languages/php/scope-resolver.js +361 -0
  328. package/dist/core/code/engine/core/ingestion/languages/php/simple-hooks.js +116 -0
  329. package/dist/core/code/engine/core/ingestion/languages/php.js +302 -0
  330. package/dist/core/code/engine/core/ingestion/languages/python/arity-metadata.js +49 -0
  331. package/dist/core/code/engine/core/ingestion/languages/python/arity.js +41 -0
  332. package/dist/core/code/engine/core/ingestion/languages/python/cache-stats.js +34 -0
  333. package/dist/core/code/engine/core/ingestion/languages/python/captures.js +299 -0
  334. package/dist/core/code/engine/core/ingestion/languages/python/depends-references.js +68 -0
  335. package/dist/core/code/engine/core/ingestion/languages/python/import-decomposer.js +115 -0
  336. package/dist/core/code/engine/core/ingestion/languages/python/import-target.js +440 -0
  337. package/dist/core/code/engine/core/ingestion/languages/python/index-stats.js +30 -0
  338. package/dist/core/code/engine/core/ingestion/languages/python/index.js +96 -0
  339. package/dist/core/code/engine/core/ingestion/languages/python/interpret.js +430 -0
  340. package/dist/core/code/engine/core/ingestion/languages/python/merge-bindings.js +47 -0
  341. package/dist/core/code/engine/core/ingestion/languages/python/query.js +323 -0
  342. package/dist/core/code/engine/core/ingestion/languages/python/receiver-binding.js +310 -0
  343. package/dist/core/code/engine/core/ingestion/languages/python/scope-resolver.js +80 -0
  344. package/dist/core/code/engine/core/ingestion/languages/python/simple-hooks.js +53 -0
  345. package/dist/core/code/engine/core/ingestion/languages/python.js +140 -0
  346. package/dist/core/code/engine/core/ingestion/languages/ruby/arity.js +41 -0
  347. package/dist/core/code/engine/core/ingestion/languages/ruby/cache-stats.js +21 -0
  348. package/dist/core/code/engine/core/ingestion/languages/ruby/captures.js +864 -0
  349. package/dist/core/code/engine/core/ingestion/languages/ruby/import-target.js +88 -0
  350. package/dist/core/code/engine/core/ingestion/languages/ruby/index.js +29 -0
  351. package/dist/core/code/engine/core/ingestion/languages/ruby/interpret.js +115 -0
  352. package/dist/core/code/engine/core/ingestion/languages/ruby/merge-bindings.js +21 -0
  353. package/dist/core/code/engine/core/ingestion/languages/ruby/query.js +349 -0
  354. package/dist/core/code/engine/core/ingestion/languages/ruby/receiver-binding.js +70 -0
  355. package/dist/core/code/engine/core/ingestion/languages/ruby/scope-resolver.js +263 -0
  356. package/dist/core/code/engine/core/ingestion/languages/ruby/simple-hooks.js +68 -0
  357. package/dist/core/code/engine/core/ingestion/languages/ruby.js +215 -0
  358. package/dist/core/code/engine/core/ingestion/languages/rust/arity.js +16 -0
  359. package/dist/core/code/engine/core/ingestion/languages/rust/cache-stats.js +21 -0
  360. package/dist/core/code/engine/core/ingestion/languages/rust/captures.js +304 -0
  361. package/dist/core/code/engine/core/ingestion/languages/rust/import-decomposer.js +167 -0
  362. package/dist/core/code/engine/core/ingestion/languages/rust/import-target.js +108 -0
  363. package/dist/core/code/engine/core/ingestion/languages/rust/index.js +29 -0
  364. package/dist/core/code/engine/core/ingestion/languages/rust/interpret.js +201 -0
  365. package/dist/core/code/engine/core/ingestion/languages/rust/merge-bindings.js +21 -0
  366. package/dist/core/code/engine/core/ingestion/languages/rust/method-owners.js +76 -0
  367. package/dist/core/code/engine/core/ingestion/languages/rust/module-path.js +222 -0
  368. package/dist/core/code/engine/core/ingestion/languages/rust/qualified-call.js +482 -0
  369. package/dist/core/code/engine/core/ingestion/languages/rust/query.js +280 -0
  370. package/dist/core/code/engine/core/ingestion/languages/rust/range-binding.js +687 -0
  371. package/dist/core/code/engine/core/ingestion/languages/rust/receiver-binding.js +148 -0
  372. package/dist/core/code/engine/core/ingestion/languages/rust/scope-resolver.js +151 -0
  373. package/dist/core/code/engine/core/ingestion/languages/rust/simple-hooks.js +32 -0
  374. package/dist/core/code/engine/core/ingestion/languages/rust.js +183 -0
  375. package/dist/core/code/engine/core/ingestion/languages/swift/arity-metadata.js +44 -0
  376. package/dist/core/code/engine/core/ingestion/languages/swift/arity.js +45 -0
  377. package/dist/core/code/engine/core/ingestion/languages/swift/base-type.js +30 -0
  378. package/dist/core/code/engine/core/ingestion/languages/swift/cache-stats.js +32 -0
  379. package/dist/core/code/engine/core/ingestion/languages/swift/captures.js +594 -0
  380. package/dist/core/code/engine/core/ingestion/languages/swift/conditional-directive-preprocess.js +256 -0
  381. package/dist/core/code/engine/core/ingestion/languages/swift/implicit-imports.js +60 -0
  382. package/dist/core/code/engine/core/ingestion/languages/swift/import-decomposer.js +87 -0
  383. package/dist/core/code/engine/core/ingestion/languages/swift/import-target.js +84 -0
  384. package/dist/core/code/engine/core/ingestion/languages/swift/index.js +56 -0
  385. package/dist/core/code/engine/core/ingestion/languages/swift/interpret.js +93 -0
  386. package/dist/core/code/engine/core/ingestion/languages/swift/merge-bindings.js +51 -0
  387. package/dist/core/code/engine/core/ingestion/languages/swift/query.js +226 -0
  388. package/dist/core/code/engine/core/ingestion/languages/swift/receiver-binding.js +169 -0
  389. package/dist/core/code/engine/core/ingestion/languages/swift/scope-resolver.js +192 -0
  390. package/dist/core/code/engine/core/ingestion/languages/swift/sibling-type-bindings.js +68 -0
  391. package/dist/core/code/engine/core/ingestion/languages/swift/signature-bindings.js +69 -0
  392. package/dist/core/code/engine/core/ingestion/languages/swift/simple-hooks.js +65 -0
  393. package/dist/core/code/engine/core/ingestion/languages/swift/target-grouping.js +97 -0
  394. package/dist/core/code/engine/core/ingestion/languages/swift/target-siblings.js +74 -0
  395. package/dist/core/code/engine/core/ingestion/languages/swift.js +246 -0
  396. package/dist/core/code/engine/core/ingestion/languages/typescript/arity-metadata.js +106 -0
  397. package/dist/core/code/engine/core/ingestion/languages/typescript/arity.js +57 -0
  398. package/dist/core/code/engine/core/ingestion/languages/typescript/array-callback.js +58 -0
  399. package/dist/core/code/engine/core/ingestion/languages/typescript/cache-stats.js +34 -0
  400. package/dist/core/code/engine/core/ingestion/languages/typescript/captures.js +956 -0
  401. package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-export-assignment.js +535 -0
  402. package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-module-exports.js +196 -0
  403. package/dist/core/code/engine/core/ingestion/languages/typescript/import-decomposer.js +374 -0
  404. package/dist/core/code/engine/core/ingestion/languages/typescript/import-target.js +65 -0
  405. package/dist/core/code/engine/core/ingestion/languages/typescript/index.js +108 -0
  406. package/dist/core/code/engine/core/ingestion/languages/typescript/interpret.js +344 -0
  407. package/dist/core/code/engine/core/ingestion/languages/typescript/merge-bindings.js +161 -0
  408. package/dist/core/code/engine/core/ingestion/languages/typescript/nuxt-auto-imports.js +325 -0
  409. package/dist/core/code/engine/core/ingestion/languages/typescript/query.js +1328 -0
  410. package/dist/core/code/engine/core/ingestion/languages/typescript/receiver-binding.js +201 -0
  411. package/dist/core/code/engine/core/ingestion/languages/typescript/scope-resolver.js +293 -0
  412. package/dist/core/code/engine/core/ingestion/languages/typescript/simple-hooks.js +139 -0
  413. package/dist/core/code/engine/core/ingestion/languages/typescript.js +455 -0
  414. package/dist/core/code/engine/core/ingestion/languages/vue/captures.js +70 -0
  415. package/dist/core/code/engine/core/ingestion/languages/vue/import-target.js +61 -0
  416. package/dist/core/code/engine/core/ingestion/languages/vue/index.js +55 -0
  417. package/dist/core/code/engine/core/ingestion/languages/vue/scope-resolver.js +295 -0
  418. package/dist/core/code/engine/core/ingestion/languages/vue.js +96 -0
  419. package/dist/core/code/engine/core/ingestion/local-symbol-pruner.js +68 -0
  420. package/dist/core/code/engine/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  421. package/dist/core/code/engine/core/ingestion/method-extractors/configs/csharp.js +290 -0
  422. package/dist/core/code/engine/core/ingestion/method-extractors/configs/dart.js +392 -0
  423. package/dist/core/code/engine/core/ingestion/method-extractors/configs/go.js +179 -0
  424. package/dist/core/code/engine/core/ingestion/method-extractors/configs/jvm.js +350 -0
  425. package/dist/core/code/engine/core/ingestion/method-extractors/configs/php.js +306 -0
  426. package/dist/core/code/engine/core/ingestion/method-extractors/configs/python.js +312 -0
  427. package/dist/core/code/engine/core/ingestion/method-extractors/configs/ruby.js +289 -0
  428. package/dist/core/code/engine/core/ingestion/method-extractors/configs/rust.js +198 -0
  429. package/dist/core/code/engine/core/ingestion/method-extractors/configs/swift.js +286 -0
  430. package/dist/core/code/engine/core/ingestion/method-extractors/configs/typescript-javascript.js +341 -0
  431. package/dist/core/code/engine/core/ingestion/method-extractors/generic.js +209 -0
  432. package/dist/core/code/engine/core/ingestion/method-types.js +3 -0
  433. package/dist/core/code/engine/core/ingestion/model/field-registry.js +41 -0
  434. package/dist/core/code/engine/core/ingestion/model/index.js +52 -0
  435. package/dist/core/code/engine/core/ingestion/model/method-registry.js +138 -0
  436. package/dist/core/code/engine/core/ingestion/model/owned-members-lookup.js +46 -0
  437. package/dist/core/code/engine/core/ingestion/model/registration-table.js +234 -0
  438. package/dist/core/code/engine/core/ingestion/model/resolve.js +183 -0
  439. package/dist/core/code/engine/core/ingestion/model/scope-resolution-indexes.js +43 -0
  440. package/dist/core/code/engine/core/ingestion/model/semantic-model.js +179 -0
  441. package/dist/core/code/engine/core/ingestion/model/symbol-table.js +216 -0
  442. package/dist/core/code/engine/core/ingestion/model/type-registry.js +84 -0
  443. package/dist/core/code/engine/core/ingestion/mro-processor.js +709 -0
  444. package/dist/core/code/engine/core/ingestion/parsing-processor.js +312 -0
  445. package/dist/core/code/engine/core/ingestion/pipeline-phases/communities.js +69 -0
  446. package/dist/core/code/engine/core/ingestion/pipeline-phases/cross-file.js +71 -0
  447. package/dist/core/code/engine/core/ingestion/pipeline-phases/di.js +338 -0
  448. package/dist/core/code/engine/core/ingestion/pipeline-phases/http-api-calls.js +312 -0
  449. package/dist/core/code/engine/core/ingestion/pipeline-phases/index.js +54 -0
  450. package/dist/core/code/engine/core/ingestion/pipeline-phases/mro.js +40 -0
  451. package/dist/core/code/engine/core/ingestion/pipeline-phases/orm.js +78 -0
  452. package/dist/core/code/engine/core/ingestion/pipeline-phases/parse-impl.js +1286 -0
  453. package/dist/core/code/engine/core/ingestion/pipeline-phases/parse.js +41 -0
  454. package/dist/core/code/engine/core/ingestion/pipeline-phases/processes.js +193 -0
  455. package/dist/core/code/engine/core/ingestion/pipeline-phases/prune-local-symbols.js +29 -0
  456. package/dist/core/code/engine/core/ingestion/pipeline-phases/registry.js +52 -0
  457. package/dist/core/code/engine/core/ingestion/pipeline-phases/routes.js +409 -0
  458. package/dist/core/code/engine/core/ingestion/pipeline-phases/rpc-edges.js +301 -0
  459. package/dist/core/code/engine/core/ingestion/pipeline-phases/runner.js +207 -0
  460. package/dist/core/code/engine/core/ingestion/pipeline-phases/scan.js +49 -0
  461. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-aop.js +442 -0
  462. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-auto-configuration.js +264 -0
  463. package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-config.js +440 -0
  464. package/dist/core/code/engine/core/ingestion/pipeline-phases/structure.js +38 -0
  465. package/dist/core/code/engine/core/ingestion/pipeline-phases/tools.js +89 -0
  466. package/dist/core/code/engine/core/ingestion/pipeline-phases/types.js +40 -0
  467. package/dist/core/code/engine/core/ingestion/pipeline.js +152 -0
  468. package/dist/core/code/engine/core/ingestion/process-processor.js +325 -0
  469. package/dist/core/code/engine/core/ingestion/resolve-references.js +205 -0
  470. package/dist/core/code/engine/core/ingestion/route-extractors/constant-resolver.js +135 -0
  471. package/dist/core/code/engine/core/ingestion/route-extractors/django-root-discovery.js +221 -0
  472. package/dist/core/code/engine/core/ingestion/route-extractors/django.js +428 -0
  473. package/dist/core/code/engine/core/ingestion/route-extractors/expo.js +39 -0
  474. package/dist/core/code/engine/core/ingestion/route-extractors/fastapi-router-bindings.js +264 -0
  475. package/dist/core/code/engine/core/ingestion/route-extractors/laravel.js +501 -0
  476. package/dist/core/code/engine/core/ingestion/route-extractors/middleware.js +175 -0
  477. package/dist/core/code/engine/core/ingestion/route-extractors/nextjs.js +81 -0
  478. package/dist/core/code/engine/core/ingestion/route-extractors/php.js +25 -0
  479. package/dist/core/code/engine/core/ingestion/route-extractors/python-const-resolver.js +307 -0
  480. package/dist/core/code/engine/core/ingestion/route-extractors/response-shapes.js +299 -0
  481. package/dist/core/code/engine/core/ingestion/route-extractors/route-path.js +71 -0
  482. package/dist/core/code/engine/core/ingestion/route-extractors/spring-shared.js +310 -0
  483. package/dist/core/code/engine/core/ingestion/route-extractors/spring.js +441 -0
  484. package/dist/core/code/engine/core/ingestion/scope-extractor-bridge.js +60 -0
  485. package/dist/core/code/engine/core/ingestion/scope-extractor.js +1373 -0
  486. package/dist/core/code/engine/core/ingestion/scope-resolution/contract/scope-resolver.js +282 -0
  487. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +72 -0
  488. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/edges.js +194 -0
  489. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/ids.js +472 -0
  490. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +49 -0
  491. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +43 -0
  492. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +274 -0
  493. package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +93 -0
  494. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/callable-value-flow.js +1240 -0
  495. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/compound-receiver.js +1174 -0
  496. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/free-call-fallback.js +873 -0
  497. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/imported-return-types.js +226 -0
  498. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/mro.js +107 -0
  499. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/overload-narrowing.js +441 -0
  500. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/property-dispatch.js +122 -0
  501. package/dist/core/code/engine/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1720 -0
  502. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/phase.js +395 -0
  503. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +208 -0
  504. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/registry.js +49 -0
  505. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/run.js +632 -0
  506. package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +112 -0
  507. package/dist/core/code/engine/core/ingestion/scope-resolution/resolution-outcome.js +41 -0
  508. package/dist/core/code/engine/core/ingestion/scope-resolution/scope/namespace-targets.js +81 -0
  509. package/dist/core/code/engine/core/ingestion/scope-resolution/scope/walkers.js +1835 -0
  510. package/dist/core/code/engine/core/ingestion/scope-resolution/unresolved-receivers.js +242 -0
  511. package/dist/core/code/engine/core/ingestion/scope-resolution/utils/definition-id.js +22 -0
  512. package/dist/core/code/engine/core/ingestion/scope-resolution/workspace-index.js +151 -0
  513. package/dist/core/code/engine/core/ingestion/structure-processor.js +40 -0
  514. package/dist/core/code/engine/core/ingestion/tree-sitter-queries.js +2244 -0
  515. package/dist/core/code/engine/core/ingestion/ts-js-hoc-utils.js +115 -0
  516. package/dist/core/code/engine/core/ingestion/type-env.js +1136 -0
  517. package/dist/core/code/engine/core/ingestion/type-extractors/c-cpp.js +555 -0
  518. package/dist/core/code/engine/core/ingestion/type-extractors/csharp.js +570 -0
  519. package/dist/core/code/engine/core/ingestion/type-extractors/dart.js +372 -0
  520. package/dist/core/code/engine/core/ingestion/type-extractors/go.js +508 -0
  521. package/dist/core/code/engine/core/ingestion/type-extractors/jvm.js +875 -0
  522. package/dist/core/code/engine/core/ingestion/type-extractors/php.js +537 -0
  523. package/dist/core/code/engine/core/ingestion/type-extractors/python.js +477 -0
  524. package/dist/core/code/engine/core/ingestion/type-extractors/ruby.js +380 -0
  525. package/dist/core/code/engine/core/ingestion/type-extractors/rust.js +502 -0
  526. package/dist/core/code/engine/core/ingestion/type-extractors/shared.js +843 -0
  527. package/dist/core/code/engine/core/ingestion/type-extractors/swift.js +490 -0
  528. package/dist/core/code/engine/core/ingestion/type-extractors/types.js +2 -0
  529. package/dist/core/code/engine/core/ingestion/type-extractors/typescript.js +690 -0
  530. package/dist/core/code/engine/core/ingestion/utils/ast-helpers.js +1693 -0
  531. package/dist/core/code/engine/core/ingestion/utils/call-analysis.js +779 -0
  532. package/dist/core/code/engine/core/ingestion/utils/callable-flow-captures.js +932 -0
  533. package/dist/core/code/engine/core/ingestion/utils/callable-labels.js +49 -0
  534. package/dist/core/code/engine/core/ingestion/utils/deferred-resolution-profile.js +151 -0
  535. package/dist/core/code/engine/core/ingestion/utils/effective-ram.js +67 -0
  536. package/dist/core/code/engine/core/ingestion/utils/env.js +60 -0
  537. package/dist/core/code/engine/core/ingestion/utils/event-loop.js +9 -0
  538. package/dist/core/code/engine/core/ingestion/utils/graph-sort.js +103 -0
  539. package/dist/core/code/engine/core/ingestion/utils/heap-probe.js +45 -0
  540. package/dist/core/code/engine/core/ingestion/utils/heritage-marker.js +47 -0
  541. package/dist/core/code/engine/core/ingestion/utils/line-base.js +24 -0
  542. package/dist/core/code/engine/core/ingestion/utils/max-file-size.js +59 -0
  543. package/dist/core/code/engine/core/ingestion/utils/method-props.js +198 -0
  544. package/dist/core/code/engine/core/ingestion/utils/qualified-name.js +73 -0
  545. package/dist/core/code/engine/core/ingestion/utils/receiver-chain-captures.js +60 -0
  546. package/dist/core/code/engine/core/ingestion/utils/receiver-chain-codec.js +188 -0
  547. package/dist/core/code/engine/core/ingestion/utils/scope-tree-walk.js +36 -0
  548. package/dist/core/code/engine/core/ingestion/utils/symbol-labels.js +48 -0
  549. package/dist/core/code/engine/core/ingestion/utils/template-arguments.js +187 -0
  550. package/dist/core/code/engine/core/ingestion/utils/type-parameters.js +209 -0
  551. package/dist/core/code/engine/core/ingestion/utils/verbose.js +6 -0
  552. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/c-cpp.js +133 -0
  553. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/csharp.js +66 -0
  554. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/dart.js +111 -0
  555. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/go.js +153 -0
  556. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/jvm.js +145 -0
  557. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/php.js +61 -0
  558. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/python.js +104 -0
  559. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/ruby.js +55 -0
  560. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/rust.js +79 -0
  561. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/swift.js +91 -0
  562. package/dist/core/code/engine/core/ingestion/variable-extractors/configs/typescript-javascript.js +86 -0
  563. package/dist/core/code/engine/core/ingestion/variable-extractors/generic.js +111 -0
  564. package/dist/core/code/engine/core/ingestion/variable-types.js +3 -0
  565. package/dist/core/code/engine/core/ingestion/vue-sfc-extractor.js +544 -0
  566. package/dist/core/code/engine/core/ingestion/workers/callable-id.js +122 -0
  567. package/dist/core/code/engine/core/ingestion/workers/clone-safety.js +470 -0
  568. package/dist/core/code/engine/core/ingestion/workers/parse-worker.js +2456 -0
  569. package/dist/core/code/engine/core/ingestion/workers/post-result.js +90 -0
  570. package/dist/core/code/engine/core/ingestion/workers/quarantine.js +41 -0
  571. package/dist/core/code/engine/core/ingestion/workers/result-merge.js +59 -0
  572. package/dist/core/code/engine/core/ingestion/workers/worker-pool.js +1725 -0
  573. package/dist/core/code/engine/core/ingestion/workspace-config.js +139 -0
  574. package/dist/core/code/engine/core/lbug/conn-lock.js +72 -0
  575. package/dist/core/code/engine/core/lbug/csv-generator.js +710 -0
  576. package/dist/core/code/engine/core/lbug/cypher-escape.js +24 -0
  577. package/dist/core/code/engine/core/lbug/extension-load-error.js +339 -0
  578. package/dist/core/code/engine/core/lbug/extension-loader.js +261 -0
  579. package/dist/core/code/engine/core/lbug/graph-emit-sink.js +584 -0
  580. package/dist/core/code/engine/core/lbug/lbug-adapter.js +2703 -0
  581. package/dist/core/code/engine/core/lbug/lbug-config.js +1029 -0
  582. package/dist/core/code/engine/core/lbug/native-check.js +435 -0
  583. package/dist/core/code/engine/core/lbug/pool-adapter.js +973 -0
  584. package/dist/core/code/engine/core/lbug/query-params.js +25 -0
  585. package/dist/core/code/engine/core/lbug/query-result-utils.js +31 -0
  586. package/dist/core/code/engine/core/lbug/rel-pair-routing.js +373 -0
  587. package/dist/core/code/engine/core/lbug/schema.js +771 -0
  588. package/dist/core/code/engine/core/lbug/shutdown-helpers.js +40 -0
  589. package/dist/core/code/engine/core/lbug/sidecar-recovery.js +716 -0
  590. package/dist/core/code/engine/core/lbug/stdio-capture.js +49 -0
  591. package/dist/core/code/engine/core/lbug/sync-csv-writer.js +115 -0
  592. package/dist/core/code/engine/core/lbug/wal-checkpoint-driver.js +215 -0
  593. package/dist/core/code/engine/core/lbug/wal-driver-state.js +28 -0
  594. package/dist/core/code/engine/core/logger.js +339 -0
  595. package/dist/core/code/engine/core/platform/capabilities.js +91 -0
  596. package/dist/core/code/engine/core/run-analyze.js +1098 -0
  597. package/dist/core/code/engine/core/tree-sitter/parser-loader.js +281 -0
  598. package/dist/core/code/engine/core/tree-sitter/safe-parse.js +258 -0
  599. package/dist/core/code/engine/core/tree-sitter/vendored-grammars.js +64 -0
  600. package/dist/core/code/engine/lib/utils.js +121 -0
  601. package/dist/core/code/engine/mcp/core/lbug-adapter.js +27 -0
  602. package/dist/core/code/engine/mcp/local/aop-metadata.js +230 -0
  603. package/dist/core/code/engine/mcp/local/bean-metadata.js +49 -0
  604. package/dist/core/code/engine/mcp/local/limits.js +15 -0
  605. package/dist/core/code/engine/mcp/local/line-display.js +6 -0
  606. package/dist/core/code/engine/mcp/local/local-backend.js +4142 -0
  607. package/dist/core/code/engine/storage/branch-index.js +72 -0
  608. package/dist/core/code/engine/storage/file-hash.js +95 -0
  609. package/dist/core/code/engine/storage/fs-atomic.js +34 -0
  610. package/dist/core/code/engine/storage/git.js +555 -0
  611. package/dist/core/code/engine/storage/index-lock.js +664 -0
  612. package/dist/core/code/engine/storage/parse-cache.js +650 -0
  613. package/dist/core/code/engine/storage/parsedfile-store.js +620 -0
  614. package/dist/core/code/engine/storage/repo-manager.js +1061 -0
  615. package/dist/core/code/engine/storage/scope-index-store.js +247 -0
  616. package/dist/core/code/engine/types/pipeline.js +2 -0
  617. package/dist/core/code/scripts/install-duckdb-extension.mjs +125 -0
  618. package/dist/core/code/scripts/resolve-analyze-cmd.cjs +346 -0
  619. package/dist/core/code/shared/graph/types.js +8 -0
  620. package/dist/core/code/shared/index.js +105 -0
  621. package/dist/core/code/shared/integrations/circuit-breaker.js +242 -0
  622. package/dist/core/code/shared/integrations/resilient-fetch.js +224 -0
  623. package/dist/core/code/shared/integrations/retry.js +70 -0
  624. package/dist/core/code/shared/integrations/understand-quickly.js +145 -0
  625. package/dist/core/code/shared/language-detection.js +162 -0
  626. package/dist/core/code/shared/languages.js +27 -0
  627. package/dist/core/code/shared/lbug/schema-constants.js +98 -0
  628. package/dist/core/code/shared/mro-strategy.js +2 -0
  629. package/dist/core/code/shared/pipeline.js +5 -0
  630. package/dist/core/code/shared/scope-resolution/callable-flow-site.js +11 -0
  631. package/dist/core/code/shared/scope-resolution/def-index.js +53 -0
  632. package/dist/core/code/shared/scope-resolution/evidence-weights.js +87 -0
  633. package/dist/core/code/shared/scope-resolution/finalize-algorithm.js +807 -0
  634. package/dist/core/code/shared/scope-resolution/language-classification.js +46 -0
  635. package/dist/core/code/shared/scope-resolution/method-dispatch-index.js +100 -0
  636. package/dist/core/code/shared/scope-resolution/module-scope-index.js +59 -0
  637. package/dist/core/code/shared/scope-resolution/origin-priority.js +23 -0
  638. package/dist/core/code/shared/scope-resolution/parsed-file.js +54 -0
  639. package/dist/core/code/shared/scope-resolution/position-index.js +136 -0
  640. package/dist/core/code/shared/scope-resolution/qualified-name-index.js +77 -0
  641. package/dist/core/code/shared/scope-resolution/reference-site.js +24 -0
  642. package/dist/core/code/shared/scope-resolution/registries/class-registry.js +32 -0
  643. package/dist/core/code/shared/scope-resolution/registries/context.js +52 -0
  644. package/dist/core/code/shared/scope-resolution/registries/evidence.js +152 -0
  645. package/dist/core/code/shared/scope-resolution/registries/field-registry.js +33 -0
  646. package/dist/core/code/shared/scope-resolution/registries/lookup-core.js +392 -0
  647. package/dist/core/code/shared/scope-resolution/registries/lookup-qualified.js +58 -0
  648. package/dist/core/code/shared/scope-resolution/registries/macro-registry.js +34 -0
  649. package/dist/core/code/shared/scope-resolution/registries/method-registry.js +34 -0
  650. package/dist/core/code/shared/scope-resolution/registries/tie-breaks.js +63 -0
  651. package/dist/core/code/shared/scope-resolution/resolve-type-ref.js +128 -0
  652. package/dist/core/code/shared/scope-resolution/scope-id.js +49 -0
  653. package/dist/core/code/shared/scope-resolution/scope-tree.js +225 -0
  654. package/dist/core/code/shared/scope-resolution/symbol-definition.js +12 -0
  655. package/dist/core/code/shared/scope-resolution/types.js +25 -0
  656. package/dist/core/code/shared/test-helpers.js +17 -0
  657. package/dist/core/code/vendor/leiden/index.cjs +355 -0
  658. package/dist/core/code/vendor/leiden/utils.cjs +419 -0
  659. package/dist/core/timeline/cli.d.ts.map +1 -1
  660. package/dist/core/timeline/cli.js +13 -6
  661. package/dist/core/timeline/cli.js.map +1 -1
  662. package/dist/core/timeline/debris.d.ts +20 -0
  663. package/dist/core/timeline/debris.d.ts.map +1 -0
  664. package/dist/core/timeline/debris.js +124 -0
  665. package/dist/core/timeline/debris.js.map +1 -0
  666. package/dist/core/timeline/hook-runner.d.ts.map +1 -1
  667. package/dist/core/timeline/hook-runner.js +3 -1
  668. package/dist/core/timeline/hook-runner.js.map +1 -1
  669. package/dist/core/timeline/hooks.d.ts.map +1 -1
  670. package/dist/core/timeline/hooks.js +13 -5
  671. package/dist/core/timeline/hooks.js.map +1 -1
  672. package/dist/core/timeline/installer.d.ts +2 -0
  673. package/dist/core/timeline/installer.d.ts.map +1 -1
  674. package/dist/core/timeline/installer.js +12 -0
  675. package/dist/core/timeline/installer.js.map +1 -1
  676. package/dist/core/timeline/project-root.d.ts +21 -0
  677. package/dist/core/timeline/project-root.d.ts.map +1 -0
  678. package/dist/core/timeline/project-root.js +83 -0
  679. package/dist/core/timeline/project-root.js.map +1 -0
  680. package/package.json +1 -1
@@ -0,0 +1,1693 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLeadingDocDescriptionExtractor = exports.DOC_BEARING_LABELS = exports.stripBidiAndZeroWidth = exports.SPLIT_SIGNATURE_NODE_TYPES = exports.LOCAL_SCOPE_BODY_NODE_TYPES = exports.PARAMETER_LIST_NODE_TYPES = exports.CALL_ARGUMENT_LIST_TYPES = exports.inferFunctionLabel = exports.CONSTRUCTOR_LABEL_NODE_TYPES = exports.METHOD_LABEL_NODE_TYPES = exports.genericFuncName = exports.findSiblingChild = exports.findEnclosingClassId = exports.isThisMemberAssignmentNode = exports.isCjsDefaultExportAssignment = exports.isPrototypeMemberAssignmentNode = exports.thisAssignmentOwnerName = exports.prototypeAssignmentOwnerName = exports.findMemberAssignmentOwnerInfo = exports.findObjectLiteralBindingInfo = exports.findEnclosingClassInfo = exports.synthesizeJavaTypeIdentity = exports.javaLocalTypeDeclarationContainer = exports.CONTAINER_TYPE_TO_LABEL = exports.MEMBER_OWNER_NODE_TYPES = exports.CLASS_CONTAINER_TYPES = exports.FUNCTION_NODE_TYPES = exports.buildDefinitionPreScan = exports.isValueDefinitionLabel = exports.isSuppressedConcreteTypedefDuplicate = exports.getDefinitionNodeFromCaptures = exports.DEFINITION_CAPTURE_KEYS = exports.isQualifiableScopeLabel = exports.qualifyRustImplTargetByModScope = exports.qualifyByEnclosingModScope = void 0;
4
+ exports.walkNamedTree = walkNamedTree;
5
+ exports.findAncestorBeforeBoundary = findAncestorBeforeBoundary;
6
+ exports.findSplitBodyCallableAncestor = findSplitBodyCallableAncestor;
7
+ exports.getLabelFromCaptures = getLabelFromCaptures;
8
+ exports.findDescendant = findDescendant;
9
+ exports.extractStringContent = extractStringContent;
10
+ exports.findChild = findChild;
11
+ exports.extractLeadingDocComment = extractLeadingDocComment;
12
+ exports.nodeToCapture = nodeToCapture;
13
+ exports.syntheticCapture = syntheticCapture;
14
+ exports.findNodeAtRange = findNodeAtRange;
15
+ exports.nodeIfType = nodeIfType;
16
+ const utils_js_1 = require("../../../lib/utils.js");
17
+ const template_arguments_js_1 = require("./template-arguments.js");
18
+ const qualified_name_js_1 = require("./qualified-name.js");
19
+ const callable_labels_js_1 = require("./callable-labels.js");
20
+ /**
21
+ * Qualify a name by its enclosing `mod_item` scope, so two same-tail items nested
22
+ * under different modules get DISTINCT paths (`outer.Inner` vs `other.Inner`).
23
+ * Walks `mod_item` ancestors (outermost → innermost) and joins them with the
24
+ * normalized raw text via the shared `splitQualifiedName`. Keyed purely on
25
+ * tree-sitter node types (no language name), so it is a no-op for every grammar
26
+ * without such a node.
27
+ *
28
+ * TWO callers, with different contracts — read both before widening either:
29
+ *
30
+ * 1. The inherent-impl target (`impl Inner { … }`) — the #1982 follow-up to
31
+ * #1975, reachable through the {@link qualifyRustImplTargetByModScope} alias
32
+ * and mirrored by the inherent-impl branch in `findEnclosingClassInfo` so the
33
+ * owner edge and the node id agree byte-for-byte. That caller gates on an
34
+ * UNSCOPED `type_identifier`, which is what keeps a SCOPED `impl a::Inner` on
35
+ * its full raw text.
36
+ *
37
+ * 2. Free items, for module node identity (#2742). That caller gates on the node
38
+ * being on neither side of an owner edge (`MEMBER_OWNER_NODE_TYPES`,
39
+ * `enclosingClassInfo`) and not inside a callable, because only the id moves
40
+ * here — every owner-edge anchor is minted separately and does not follow.
41
+ *
42
+ * A name with NO enclosing `mod` is returned verbatim, never normalized: rewriting
43
+ * a scoped target's separator (`a::Inner` → `a.Inner`) would move its node id away
44
+ * from the id its owner edge emits, which is how caller 2 first broke caller 1's
45
+ * #1975 contract. Splitting an unscoped name has always been the identity, so
46
+ * caller 1 is unaffected either way.
47
+ */
48
+ const qualifyByEnclosingModScope = (node, rawText) => {
49
+ const modSegments = [];
50
+ let current = node.parent;
51
+ while (current) {
52
+ if (current.type === 'mod_item') {
53
+ const nameNode = current.childForFieldName?.('name') ??
54
+ current.children?.find((c) => c.type === 'identifier');
55
+ if (nameNode)
56
+ modSegments.unshift(nameNode.text);
57
+ }
58
+ current = current.parent;
59
+ }
60
+ // No enclosing `mod`: return the raw text UNTOUCHED. Normalizing here would
61
+ // rewrite a scoped target's separator (`a::Inner` -> `a.Inner`) and silently
62
+ // move its node id away from the one the owner edge emits, which is how this
63
+ // helper first broke the #1975 scoped-impl ownership when it was generalized
64
+ // beyond unscoped targets. Callers that pass an unscoped name are unaffected,
65
+ // since splitting one has always been the identity.
66
+ if (modSegments.length === 0)
67
+ return rawText;
68
+ return [...modSegments, ...(0, qualified_name_js_1.splitQualifiedName)(rawText)].filter(Boolean).join('.');
69
+ };
70
+ exports.qualifyByEnclosingModScope = qualifyByEnclosingModScope;
71
+ /**
72
+ * Impl-target alias of {@link qualifyByEnclosingModScope}, kept as its own name
73
+ * because the caller gates it on UNSCOPED targets (see the contract above).
74
+ */
75
+ exports.qualifyRustImplTargetByModScope = exports.qualifyByEnclosingModScope;
76
+ /**
77
+ * #1991: scope-label predicate that single-sources the `nodeLabel === 'Trait'`
78
+ * checks in parsing-processor.ts / parse-worker.ts. A Ruby `module` maps to the
79
+ * `Trait` registry label but is NOT a typeDeclaration, so `extractQualifiedName`
80
+ * bails on it; these node labels are instead qualified via the scope walk
81
+ * (`qualifyScopeName`) so same-tail nested modules get distinct ids. Keeping the
82
+ * literal in one place stops the four hand-maintained copies (two each in the
83
+ * sequential and worker definition paths) from drifting apart. Pure predicate —
84
+ * value-identical to the inlined `nodeLabel === 'Trait'`.
85
+ */
86
+ const isQualifiableScopeLabel = (nodeLabel) => nodeLabel === 'Trait';
87
+ exports.isQualifiableScopeLabel = isQualifiableScopeLabel;
88
+ /**
89
+ * Ordered list of definition capture keys for tree-sitter query matches.
90
+ * Used to extract the definition node from a capture map.
91
+ */
92
+ exports.DEFINITION_CAPTURE_KEYS = [
93
+ 'definition.function',
94
+ 'definition.class',
95
+ 'definition.interface',
96
+ 'definition.method',
97
+ 'definition.struct',
98
+ 'definition.enum',
99
+ 'definition.namespace',
100
+ 'definition.module',
101
+ 'definition.trait',
102
+ 'definition.impl',
103
+ 'definition.type',
104
+ 'definition.const',
105
+ 'definition.static',
106
+ 'definition.variable',
107
+ 'definition.typedef',
108
+ 'definition.macro',
109
+ 'definition.union',
110
+ 'definition.property',
111
+ 'definition.record',
112
+ 'definition.delegate',
113
+ 'definition.annotation',
114
+ 'definition.constructor',
115
+ 'definition.template',
116
+ ];
117
+ /** Extract the definition node from a tree-sitter query capture map. */
118
+ const getDefinitionNodeFromCaptures = (captureMap) => {
119
+ for (const key of exports.DEFINITION_CAPTURE_KEYS) {
120
+ if (captureMap[key])
121
+ return captureMap[key];
122
+ }
123
+ return null;
124
+ };
125
+ exports.getDefinitionNodeFromCaptures = getDefinitionNodeFromCaptures;
126
+ const nodeRangeKey = (node) => `${node.startPosition.row}:${node.startPosition.column}:${node.endPosition.row}:${node.endPosition.column}`;
127
+ const isConcreteTypedefCapture = (captureMap) => {
128
+ const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
129
+ return (definitionNode?.type === 'type_definition' &&
130
+ (captureMap['definition.struct'] !== undefined || captureMap['definition.enum'] !== undefined));
131
+ };
132
+ const isSuppressedConcreteTypedefDuplicate = (captureMap, concreteTypedefRanges) => {
133
+ const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
134
+ return (definitionNode?.type === 'type_definition' &&
135
+ captureMap['definition.typedef'] !== undefined &&
136
+ concreteTypedefRanges.has(nodeRangeKey(definitionNode)));
137
+ };
138
+ exports.isSuppressedConcreteTypedefDuplicate = isSuppressedConcreteTypedefDuplicate;
139
+ /**
140
+ * Graph labels produced by a value capture (`@definition.const` /
141
+ * `@definition.static` / `@definition.variable`) — a binding that holds a value.
142
+ *
143
+ * `Property` is deliberately NOT here. It outranks these: Python matches both
144
+ * `@definition.property` (annotated) and `@definition.variable` (bare) on one
145
+ * assignment, and the property must win so a typed class attribute keeps its
146
+ * `Property` node and its owning `HAS_PROPERTY` edge. `Property` is instead
147
+ * suppressed only by a *callable* claim — see {@link buildDefinitionNameClaims}.
148
+ */
149
+ const VALUE_DEFINITION_LABELS = new Set([
150
+ 'Const',
151
+ 'Static',
152
+ 'Variable',
153
+ ]);
154
+ /** True when `label` is the kind of node a value capture emits. */
155
+ const isValueDefinitionLabel = (label) => VALUE_DEFINITION_LABELS.has(label);
156
+ exports.isValueDefinitionLabel = isValueDefinitionLabel;
157
+ /**
158
+ * Pre-scan `matches` for the `${definitionNode.startIndex}:${name}` keys already
159
+ * claimed by a higher-ranked definition capture, so the parse-worker's duplicate
160
+ * suppression is order-independent.
161
+ *
162
+ * Rank, highest first: callable (`Function`/`Method`/`Constructor`) → `Property`
163
+ * → value (`Const`/`Static`/`Variable`). A capture is dropped only when a
164
+ * STRICTLY higher rank claimed the same declaration node and name, so no capture
165
+ * can suppress itself and no rank can suppress a peer.
166
+ *
167
+ * ## Why this exists (#2687)
168
+ *
169
+ * `const X = () => {}` matches BOTH `@definition.function` and
170
+ * `@definition.const` on the same `lexical_declaration`. Only one graph node
171
+ * should survive — the `Function`, because that is what `CALLS` edges target.
172
+ * The parse-worker's in-loop dedup intends exactly that, but only the value
173
+ * branch consults its `processedDefinitionNodes` set, so suppression worked only
174
+ * if the function match happened to be processed first. It is not: tree-sitter
175
+ * completes the const pattern at `@name`, while the function pattern must also
176
+ * match the trailing `(arrow_function)` / `(function_expression)` value, so the
177
+ * const match is yielded FIRST and the edgeless `Const:` twin escaped.
178
+ *
179
+ * Consulting this set makes the outcome independent of match order.
180
+ *
181
+ * ## Keying
182
+ *
183
+ * Keys are `startIndex:name`, never `startIndex` alone — a multi-name
184
+ * declaration (`const a = 1, b = () => {}`) shares ONE definition node, and a
185
+ * bare-index key would wrongly suppress `a`'s legitimate `Const` node.
186
+ *
187
+ * Labels come from {@link getLabelFromCaptures}, the same function the main loop
188
+ * uses, so the pre-scan and the loop can never disagree about what counts as a
189
+ * value capture — including when a provider's `labelOverride` reclassifies one.
190
+ * A match that resolves to a value label registers nothing, so a match can never
191
+ * suppress itself.
192
+ *
193
+ * Language-agnostic: keyed off capture names and labels only.
194
+ *
195
+ * Also collects the concrete-typedef ranges that suppress the analogous
196
+ * typedef/struct duplicate, so both suppression sets come from one traversal.
197
+ */
198
+ const buildDefinitionPreScan = (matches, provider) => {
199
+ const nonValue = new Set();
200
+ const callable = new Set();
201
+ const concreteTypedefRanges = new Set();
202
+ for (const match of matches) {
203
+ // ONE capture-map build per match feeds both suppression sets. These used
204
+ // to be two independent passes over `matches` (each rebuilding this object)
205
+ // on the hot per-file parse path.
206
+ const captureMap = {};
207
+ for (const capture of match.captures) {
208
+ captureMap[capture.name] = capture.node;
209
+ }
210
+ const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
211
+ if (definitionNode === null)
212
+ continue;
213
+ if (isConcreteTypedefCapture(captureMap)) {
214
+ concreteTypedefRanges.add(nodeRangeKey(definitionNode));
215
+ }
216
+ // No `@name` capture means nothing a lower-ranked capture could collide
217
+ // with — a value or property pattern always binds a name. Checked before
218
+ // `getLabelFromCaptures` so a nameless match never pays for label
219
+ // resolution (which can reach a provider's `labelOverride`).
220
+ const nameNode = captureMap['name'];
221
+ if (nameNode === undefined)
222
+ continue;
223
+ const label = getLabelFromCaptures(captureMap, provider);
224
+ if (label === null || (0, exports.isValueDefinitionLabel)(label))
225
+ continue;
226
+ const key = `${definitionNode.startIndex}:${nameNode.text}`;
227
+ nonValue.add(key);
228
+ if ((0, callable_labels_js_1.isOverloadableCallable)(label))
229
+ callable.add(key);
230
+ }
231
+ return { nonValue, callable, concreteTypedefRanges };
232
+ };
233
+ exports.buildDefinitionPreScan = buildDefinitionPreScan;
234
+ /**
235
+ * Node types that represent function/method definitions across languages.
236
+ * Used by parent-walk in call-processor, parse-worker, and type-env to detect
237
+ * enclosing function scope boundaries.
238
+ *
239
+ * INVARIANT: This set MUST be a superset of every language's
240
+ * MethodExtractionConfig.methodNodeTypes. When adding a new node type to a
241
+ * MethodExtractor config, add it here too — otherwise enclosing-function
242
+ * resolution will silently miss that node type during parent-walks.
243
+ */
244
+ exports.FUNCTION_NODE_TYPES = new Set([
245
+ // TypeScript/JavaScript
246
+ 'function_declaration',
247
+ 'arrow_function',
248
+ 'function_expression',
249
+ 'method_definition',
250
+ 'generator_function_declaration',
251
+ // Python
252
+ 'function_definition',
253
+ // Common async variants
254
+ 'async_function_declaration',
255
+ 'async_arrow_function',
256
+ // Java
257
+ 'method_declaration',
258
+ 'constructor_declaration',
259
+ 'compact_constructor_declaration',
260
+ 'annotation_type_element_declaration',
261
+ // C/C++
262
+ // 'function_definition' already included above
263
+ // Go
264
+ // 'method_declaration' already included from Java
265
+ // C#
266
+ 'local_function_statement',
267
+ // Rust
268
+ 'function_item',
269
+ 'impl_item', // Methods inside impl blocks
270
+ // PHP
271
+ 'anonymous_function',
272
+ // Kotlin
273
+ 'lambda_literal',
274
+ 'secondary_constructor', // F48: methodNodeTypes superset invariant
275
+ // Swift
276
+ 'init_declaration',
277
+ 'deinit_declaration',
278
+ // Ruby
279
+ 'method', // def foo
280
+ 'singleton_method', // def self.foo
281
+ // Dart
282
+ 'function_signature',
283
+ 'method_signature',
284
+ ]);
285
+ /**
286
+ * AST node types that represent a class-like container (for HAS_METHOD edge extraction).
287
+ *
288
+ * INVARIANT: When a language config adds a new node type to `typeDeclarationNodes`,
289
+ * that type must also be added here AND to `CONTAINER_TYPE_TO_LABEL` below,
290
+ * otherwise `findEnclosingClassNode` won't recognize it and methods may get
291
+ * orphaned HAS_METHOD edges or incorrect labels.
292
+ */
293
+ exports.CLASS_CONTAINER_TYPES = new Set([
294
+ 'class_declaration',
295
+ 'abstract_class_declaration',
296
+ 'interface_declaration',
297
+ 'struct_declaration',
298
+ 'record_declaration',
299
+ 'class_specifier',
300
+ 'struct_specifier',
301
+ 'impl_item',
302
+ 'trait_item',
303
+ 'struct_item',
304
+ 'enum_item',
305
+ 'class_definition',
306
+ 'trait_declaration',
307
+ // PHP
308
+ 'enum_declaration',
309
+ 'protocol_declaration',
310
+ // Dart
311
+ 'mixin_declaration',
312
+ 'extension_declaration',
313
+ // Ruby
314
+ 'class',
315
+ 'module',
316
+ 'singleton_class', // Ruby: class << self
317
+ // Kotlin
318
+ 'object_declaration',
319
+ 'companion_object',
320
+ // Go
321
+ 'struct_type',
322
+ 'interface_type',
323
+ ]);
324
+ /**
325
+ * Node types whose OWN node id must not be re-keyed by an enclosing-scope
326
+ * qualifier (see {@link qualifyByEnclosingModScope}) unless the owner-edge
327
+ * anchor moves in the same change.
328
+ *
329
+ * These are the containers a member can be declared inside. Their members'
330
+ * `HAS_METHOD` / `HAS_PROPERTY` edges anchor on `findEnclosingClassInfo().classId`,
331
+ * which is minted from the container's bare `nameNode.text` further down this
332
+ * file and only follows a qualified shape when the provider opts in via
333
+ * `classExtractor.qualifiedNodeId`. So qualifying a container's id alone points
334
+ * every one of its member edges at a node that does not exist — the edges are
335
+ * dropped at COPY time and the container silently loses all its members.
336
+ *
337
+ * Derived from `CLASS_CONTAINER_TYPES` on purpose: that set is already the
338
+ * single source of "this node type owns member edges", carries the INVARIANT
339
+ * note above binding it to `CONTAINER_TYPE_TO_LABEL`, and so a language adding
340
+ * a container cannot gain a mismatched id shape here without also failing that
341
+ * invariant. Keyed purely on tree-sitter node types — no language names.
342
+ */
343
+ exports.MEMBER_OWNER_NODE_TYPES = new Set([
344
+ ...exports.CLASS_CONTAINER_TYPES,
345
+ // Rust `union_item` owns a `field_declaration_list` exactly as `struct_item`
346
+ // does, and its fields ARE captured as `Property`, but it is absent from
347
+ // `CLASS_CONTAINER_TYPES`, so `findEnclosingClassInfo` does not recognize it as
348
+ // an owner: union fields carry no `HAS_PROPERTY` edge at all and therefore
349
+ // cannot dangle. Listed here so the union's own id keeps the same shape as the
350
+ // struct beside it, and so making it a real owner later starts from a
351
+ // consistent id rather than having to move one.
352
+ 'union_item',
353
+ ]);
354
+ exports.CONTAINER_TYPE_TO_LABEL = {
355
+ class_declaration: 'Class',
356
+ abstract_class_declaration: 'Class',
357
+ interface_declaration: 'Interface',
358
+ struct_declaration: 'Struct',
359
+ struct_specifier: 'Struct',
360
+ class_specifier: 'Class',
361
+ class_definition: 'Class',
362
+ impl_item: 'Impl',
363
+ trait_item: 'Trait',
364
+ struct_item: 'Struct',
365
+ enum_item: 'Enum',
366
+ trait_declaration: 'Trait',
367
+ enum_declaration: 'Enum',
368
+ record_declaration: 'Record',
369
+ protocol_declaration: 'Interface',
370
+ mixin_declaration: 'Mixin',
371
+ extension_declaration: 'Class',
372
+ class: 'Class',
373
+ // Ruby `module` declarations map to `Trait` so they participate in the
374
+ // class-like type registry used by `lookupClassByName` / inheritance
375
+ // resolution. This lets `include` / `extend` / `prepend` mixin heritage
376
+ // resolve to the providing module. Safe for non-Ruby languages: the only supported
377
+ // grammar that uses the bare `module` AST node type as a container is
378
+ // Ruby (Rust uses `mod_item`). Any new language adding a `module` node
379
+ // type must explicitly reclassify here.
380
+ module: 'Trait',
381
+ singleton_class: 'Class', // Ruby: class << self inherits enclosing class name
382
+ object_declaration: 'Class',
383
+ companion_object: 'Class',
384
+ struct_type: 'Struct',
385
+ interface_type: 'Interface',
386
+ };
387
+ /**
388
+ * Pre-order walk over a node and all its named descendants, invoking `cb` on
389
+ * each. Replaces the per-language `visit`/`visitGo`/`visitRust`/`visitSwift`
390
+ * clones that every language's capture-synthesis walker re-implemented (#1956
391
+ * tri-review U6).
392
+ *
393
+ * Iterates by index with a null guard: `node.namedChild(i)` is typed
394
+ * `SyntaxNode | null`, and most callers already guarded it. The Go and C#
395
+ * callers previously iterated `node.namedChildren`; the Go one had no null
396
+ * guard, so this standardizes them onto the guarded indexed form — a deliberate,
397
+ * strictly-safer behavior addition (the traversal *sequence* is identical, so
398
+ * capture output stays byte-identical on well-formed trees; the guard only
399
+ * matters for a null named child, which the fixture corpus never produces).
400
+ */
401
+ function walkNamedTree(node, cb) {
402
+ cb(node);
403
+ for (let i = 0; i < node.namedChildCount; i++) {
404
+ const child = node.namedChild(i);
405
+ if (child !== null)
406
+ walkNamedTree(child, cb);
407
+ }
408
+ }
409
+ /** Return the first matching ancestor unless a boundary ancestor is reached first. */
410
+ function findAncestorBeforeBoundary(node, targetTypes, boundaryTypes) {
411
+ let current = node.parent;
412
+ while (current !== null) {
413
+ if (boundaryTypes.has(current.type))
414
+ return null;
415
+ if (targetTypes.has(current.type))
416
+ return current;
417
+ current = current.parent;
418
+ }
419
+ return null;
420
+ }
421
+ /**
422
+ * Enclosing callable for grammars that split a callable into a SIGNATURE node
423
+ * and a SIBLING body, where the callable is therefore never an ancestor of the
424
+ * code inside it.
425
+ *
426
+ * Dart is the case that forced this: `int outer() { … }` parses as
427
+ * `function_signature` followed by `function_body` as SIBLINGS, so an ancestor
428
+ * walk from a closure inside the body can never reach `outer`. No membership
429
+ * set fixes that — the walk is looking in the wrong direction (#2699).
430
+ *
431
+ * Deliberately a FALLBACK, used only when the ancestor walk found nothing.
432
+ *
433
+ * The sibling must be a BARE SIGNATURE, and that restriction is load-bearing —
434
+ * "any preceding callable sibling" is WRONG and was caught regressing PHP. In
435
+ * `<?php function target($x) {…} $handler = function ($x) {…};` the closure is
436
+ * at FILE level, so the primary ancestor walk correctly finds nothing and this
437
+ * fallback runs; an unrestricted version then grabs the preceding
438
+ * `function_definition` and mis-qualifies the file-level `$handler` as
439
+ * `target.$handler`. A preceding sibling is only an ENCLOSING callable when it
440
+ * cannot hold its own body — i.e. when the grammar split the body off.
441
+ *
442
+ * `SPLIT_SIGNATURE_NODE_TYPES` is exactly that set, and it is derived rather
443
+ * than listed: `LOCAL_SCOPE_BODY_NODE_TYPES` already filters the bare-signature
444
+ * types out of `FUNCTION_NODE_TYPES`, so the difference between them IS the
445
+ * split-signature set. PHP's `function_definition` carries a body and is in
446
+ * both, so it is excluded; Dart's `function_signature` is in only the former,
447
+ * so it qualifies.
448
+ *
449
+ * Language-neutral by construction — it names no grammar, and any future
450
+ * signature/body-split language is covered for free.
451
+ */
452
+ function findSplitBodyCallableAncestor(node, signatureOnlyTypes, boundaryTypes) {
453
+ let current = node.parent;
454
+ while (current !== null) {
455
+ if (boundaryTypes.has(current.type))
456
+ return null;
457
+ const prev = current.previousNamedSibling;
458
+ if (prev !== null &&
459
+ signatureOnlyTypes.has(prev.type) &&
460
+ // `current` must be the signature's BODY, not merely the next thing after
461
+ // it. Without this, valid TypeScript trips the fallback: in
462
+ // declare namespace Api {
463
+ // function internalHelper(x): number;
464
+ // export function send(x): number;
465
+ // }
466
+ // `send`'s `export_statement` is the next sibling of `internalHelper`'s
467
+ // `function_signature`, so `send` was mis-qualified as
468
+ // `internalHelper.send@r:c`. TypeScript emits bodyless
469
+ // function_signature/method_signature for overloads and ambient
470
+ // declarations, so the split-signature set is NOT Dart-only.
471
+ //
472
+ // A body contains statements; a declaration wrapper contains another
473
+ // signature. Rejecting any `current` that directly holds a signature of
474
+ // its own separates the two without naming a grammar.
475
+ !current.namedChildren.some((child) => signatureOnlyTypes.has(child.type))) {
476
+ return prev;
477
+ }
478
+ current = current.parent;
479
+ }
480
+ return null;
481
+ }
482
+ // SPLIT_SIGNATURE_NODE_TYPES is defined next to LOCAL_SCOPE_BODY_NODE_TYPES,
483
+ // which it derives from — declaring it here would read it in its temporal dead
484
+ // zone and throw at module load (tsc does NOT catch that; only running does).
485
+ /**
486
+ * Determine the graph node label from a tree-sitter capture map.
487
+ * Handles language-specific reclassification via the provider's labelOverride hook
488
+ * (e.g. C/C++ duplicate skipping, Kotlin Method promotion).
489
+ * Returns null if the capture should be skipped (import, call, C/C++ duplicate, missing name).
490
+ */
491
+ function getLabelFromCaptures(captureMap, provider) {
492
+ if (captureMap['import'] || captureMap['call'])
493
+ return null;
494
+ const hasDefaultExportHocNameSeed = captureMap['definition.function'] !== undefined &&
495
+ (captureMap['hoc'] !== undefined || captureMap['callee'] !== undefined);
496
+ // Nameless `definition.class` passes through: a class extractor may
497
+ // synthesize the name (Java anonymous class bodies → `Worker$N`, #2550).
498
+ // Downstream stays safe — parse-worker skips any nameless definition the
499
+ // extractor could not name (its `!nameNode && !extractedClassSymbol` gate).
500
+ if (!captureMap['name'] &&
501
+ !captureMap['definition.constructor'] &&
502
+ !captureMap['definition.class'] &&
503
+ !hasDefaultExportHocNameSeed)
504
+ return null;
505
+ if (captureMap['definition.function']) {
506
+ if (provider.labelOverride) {
507
+ const override = provider.labelOverride(captureMap['definition.function'], 'Function');
508
+ if (override !== 'Function')
509
+ return override;
510
+ }
511
+ return 'Function';
512
+ }
513
+ if (captureMap['definition.class'])
514
+ return 'Class';
515
+ if (captureMap['definition.interface'])
516
+ return 'Interface';
517
+ if (captureMap['definition.method'])
518
+ return 'Method';
519
+ if (captureMap['definition.struct'])
520
+ return 'Struct';
521
+ if (captureMap['definition.enum'])
522
+ return 'Enum';
523
+ if (captureMap['definition.namespace'])
524
+ return 'Namespace';
525
+ if (captureMap['definition.module']) {
526
+ // Let providers reclassify module captures (e.g. Ruby remaps `Module`→`Trait`
527
+ // so mixin heritage resolves through `lookupClassByName`). Returning null
528
+ // from labelOverride means "skip this symbol"; treat it as a no-op here so
529
+ // we keep the default label rather than dropping a real definition.
530
+ if (provider.labelOverride) {
531
+ const override = provider.labelOverride(captureMap['definition.module'], 'Module');
532
+ if (override && override !== 'Module')
533
+ return override;
534
+ }
535
+ return 'Module';
536
+ }
537
+ if (captureMap['definition.trait'])
538
+ return 'Trait';
539
+ if (captureMap['definition.impl'])
540
+ return 'Impl';
541
+ if (captureMap['definition.type'])
542
+ return 'TypeAlias';
543
+ if (captureMap['definition.const'])
544
+ return 'Const';
545
+ if (captureMap['definition.static'])
546
+ return 'Static';
547
+ if (captureMap['definition.variable'])
548
+ return 'Variable';
549
+ if (captureMap['definition.typedef'])
550
+ return 'Typedef';
551
+ if (captureMap['definition.macro'])
552
+ return 'Macro';
553
+ if (captureMap['definition.union'])
554
+ return 'Union';
555
+ if (captureMap['definition.property'])
556
+ return 'Property';
557
+ if (captureMap['definition.record'])
558
+ return 'Record';
559
+ if (captureMap['definition.delegate'])
560
+ return 'Delegate';
561
+ if (captureMap['definition.annotation'])
562
+ return 'Annotation';
563
+ if (captureMap['definition.constructor'])
564
+ return 'Constructor';
565
+ if (captureMap['definition.template'])
566
+ return 'Template';
567
+ return 'CodeElement';
568
+ }
569
+ /** Walk up AST to find enclosing class/struct/interface/impl, return its ID and name.
570
+ * For Go method_declaration nodes, extracts receiver type (e.g. `func (u *User) Save()` → User struct).
571
+ *
572
+ * @param resolveEnclosingOwner Optional language-specific hook for container remapping.
573
+ * When provided and a CLASS_CONTAINER_TYPES node is found, this hook is called:
574
+ * - Return a different SyntaxNode to remap the container (e.g., Ruby singleton_class → class).
575
+ * - Return `null` to skip this container and keep walking up.
576
+ * - Return the input node (identity) to use the container as-is.
577
+ * When omitted, the container node is used as-is.
578
+ *
579
+ * INVARIANT: Implementers SHOULD return either `null`, the input node, or
580
+ * another CLASS_CONTAINER_TYPES node. Returning a non-container node is
581
+ * permitted but discouraged — it will cause the walk to skip the current
582
+ * container and continue from the redirected node's parent. The
583
+ * `MAX_ENCLOSING_WALK_ITERATIONS` defense-in-depth guard below prevents
584
+ * pathological hooks from creating an infinite loop. */
585
+ const MAX_ENCLOSING_WALK_ITERATIONS = 4096;
586
+ /** Named Java declarations that can host, or themselves be, local types. */
587
+ const JAVA_NAMED_TYPE_NODE_LABELS = new Map([
588
+ ['class_declaration', 'Class'],
589
+ ['enum_declaration', 'Enum'],
590
+ ['interface_declaration', 'Interface'],
591
+ ['record_declaration', 'Record'],
592
+ ]);
593
+ const JAVA_ANON_HOST_TYPES = new Set(JAVA_NAMED_TYPE_NODE_LABELS.keys());
594
+ const JAVA_LOCAL_TYPE_CONTAINERS = new Set([
595
+ 'block',
596
+ 'constructor_body',
597
+ 'switch_block_statement_group',
598
+ ]);
599
+ /** A legal local type declaration is a class, enum, record, or interface
600
+ * directly occupying a block-statement position. Annotation interfaces are
601
+ * deliberately excluded: javac rejects local annotation declarations. */
602
+ const javaLocalTypeDeclarationContainer = (node) => {
603
+ if (!JAVA_NAMED_TYPE_NODE_LABELS.has(node.type))
604
+ return null;
605
+ const parent = node.parent;
606
+ return parent !== null && JAVA_LOCAL_TYPE_CONTAINERS.has(parent.type) ? parent : null;
607
+ };
608
+ exports.javaLocalTypeDeclarationContainer = javaLocalTypeDeclarationContainer;
609
+ const isJavaLocalTypeNode = (node) => (0, exports.javaLocalTypeDeclarationContainer)(node) !== null;
610
+ /** The two Java anonymous-class-body shapes (#2550/#2555): an
611
+ * `object_creation_expression` with a `class_body` child
612
+ * (`new Runnable() { ... }`), and an `enum_constant` with a `body:`
613
+ * field (`enum E { A { ... } }` — javac's other `E$N` shape). */
614
+ const isJavaAnonymousBodyNode = (node) => (node.type === 'object_creation_expression' &&
615
+ node.namedChildren?.some((c) => c.type === 'class_body') === true) ||
616
+ (node.type === 'enum_constant' && node.childForFieldName?.('body')?.type === 'class_body');
617
+ /** Nearest ancestor of `node` that is an enclosing type per JLS 13.1. */
618
+ const nearestJavaEnclosingType = (node) => {
619
+ let cursor = node.parent;
620
+ let iterations = 0;
621
+ while (cursor) {
622
+ if (++iterations > MAX_ENCLOSING_WALK_ITERATIONS)
623
+ return null;
624
+ if (JAVA_ANON_HOST_TYPES.has(cursor.type) || isJavaAnonymousBodyNode(cursor))
625
+ return cursor;
626
+ cursor = cursor.parent;
627
+ }
628
+ return null;
629
+ };
630
+ /** Parse-tree-bounded memo. Sequence ordinals are built once per tree, avoiding
631
+ * a host-candidate scan for every extraction/ownership consumer. */
632
+ const javaTypeIdentityMemo = new WeakMap();
633
+ const javaHostKey = (node) => `${node.type}:${node.startIndex}`;
634
+ const javaIdentityCandidatesBelow = (root) => {
635
+ const seen = new Set();
636
+ const candidates = [];
637
+ for (const type of [
638
+ 'object_creation_expression',
639
+ 'enum_constant',
640
+ ...JAVA_NAMED_TYPE_NODE_LABELS.keys(),
641
+ ]) {
642
+ for (const candidate of root.descendantsOfType?.(type) ?? []) {
643
+ if (!isJavaAnonymousBodyNode(candidate) && !isJavaLocalTypeNode(candidate))
644
+ continue;
645
+ const key = javaHostKey(candidate);
646
+ if (seen.has(key))
647
+ continue;
648
+ seen.add(key);
649
+ candidates.push(candidate);
650
+ }
651
+ }
652
+ return candidates.sort((left, right) => left.startIndex - right.startIndex);
653
+ };
654
+ const buildJavaTypeIdentityState = (root) => {
655
+ const ordinalByStart = new Map();
656
+ const sequenceCounts = new Map();
657
+ for (const candidate of javaIdentityCandidatesBelow(root)) {
658
+ const host = nearestJavaEnclosingType(candidate);
659
+ if (host === null)
660
+ continue;
661
+ const isAnonymous = isJavaAnonymousBodyNode(candidate);
662
+ const bindingName = isAnonymous ? '' : candidate.childForFieldName?.('name')?.text;
663
+ // Anonymous types deliberately use the empty sequence key; malformed named
664
+ // declarations must not enter that sequence.
665
+ if (!isAnonymous && !bindingName)
666
+ continue;
667
+ const sequenceKey = `${javaHostKey(host)}:${bindingName}`;
668
+ const ordinal = (sequenceCounts.get(sequenceKey) ?? 0) + 1;
669
+ sequenceCounts.set(sequenceKey, ordinal);
670
+ ordinalByStart.set(candidate.startIndex, ordinal);
671
+ }
672
+ return { byStart: new Map(), ordinalByStart };
673
+ };
674
+ const javaTypeIdentityStateFor = (node) => {
675
+ const tree = node.tree;
676
+ if (tree === undefined) {
677
+ const host = nearestJavaEnclosingType(node);
678
+ return buildJavaTypeIdentityState(host ?? node);
679
+ }
680
+ let state = javaTypeIdentityMemo.get(tree);
681
+ if (state === undefined) {
682
+ state = buildJavaTypeIdentityState(tree.rootNode ?? node);
683
+ javaTypeIdentityMemo.set(tree, state);
684
+ }
685
+ return state;
686
+ };
687
+ /** Source-type-relative binary name of a Java enclosing type, including
688
+ * synthesized local/anonymous hosts and named member-type chains. */
689
+ const javaBinaryNameOfType = (node) => {
690
+ if (isJavaAnonymousBodyNode(node) || isJavaLocalTypeNode(node)) {
691
+ return (0, exports.synthesizeJavaTypeIdentity)(node)?.name;
692
+ }
693
+ if (!JAVA_ANON_HOST_TYPES.has(node.type))
694
+ return undefined;
695
+ const simpleName = node.childForFieldName?.('name')?.text;
696
+ if (simpleName === undefined || simpleName.length === 0)
697
+ return undefined;
698
+ const enclosing = nearestJavaEnclosingType(node);
699
+ if (enclosing === null)
700
+ return simpleName;
701
+ const enclosingName = javaBinaryNameOfType(enclosing);
702
+ return enclosingName === undefined ? undefined : `${enclosingName}$${simpleName}`;
703
+ };
704
+ /**
705
+ * Authoritative Java local/anonymous type identity.
706
+ *
707
+ * JLS 13.1 defines the shape and immediate-host prefix. OpenJDK javac's
708
+ * Check.localClassName allocates N independently for each
709
+ * (enclosing binary name, local simple name) pair; anonymous types use the
710
+ * empty simple name and therefore have their own sequence. Package names are
711
+ * omitted from this project identity because graph ids already include the
712
+ * file path.
713
+ */
714
+ const synthesizeJavaTypeIdentity = (node) => {
715
+ const localLabel = JAVA_NAMED_TYPE_NODE_LABELS.get(node.type);
716
+ const isLocal = localLabel !== undefined && isJavaLocalTypeNode(node);
717
+ const isAnonymous = isJavaAnonymousBodyNode(node);
718
+ const enclosing = nearestJavaEnclosingType(node);
719
+ const memberSimpleName = !isLocal && !isAnonymous && localLabel !== undefined
720
+ ? node.childForFieldName?.('name')?.text
721
+ : undefined;
722
+ const synthesizedHostIdentity = memberSimpleName !== undefined && enclosing !== null
723
+ ? (0, exports.synthesizeJavaTypeIdentity)(enclosing)
724
+ : undefined;
725
+ if (!isLocal && !isAnonymous && synthesizedHostIdentity === undefined)
726
+ return undefined;
727
+ if (enclosing === null)
728
+ return undefined;
729
+ const state = javaTypeIdentityStateFor(node);
730
+ const cached = state.byStart.get(node.startIndex);
731
+ if (cached !== undefined)
732
+ return cached;
733
+ const prefix = javaBinaryNameOfType(enclosing);
734
+ if (prefix === undefined)
735
+ return undefined;
736
+ if (memberSimpleName !== undefined) {
737
+ const identity = {
738
+ name: `${prefix}$${memberSimpleName}`,
739
+ label: localLabel,
740
+ bindingName: memberSimpleName,
741
+ };
742
+ state.byStart.set(node.startIndex, identity);
743
+ return identity;
744
+ }
745
+ const bindingName = isLocal ? node.childForFieldName?.('name')?.text : undefined;
746
+ if (isLocal && !bindingName)
747
+ return undefined;
748
+ const ordinal = state.ordinalByStart.get(node.startIndex);
749
+ if (ordinal === undefined)
750
+ return undefined;
751
+ const identity = {
752
+ name: `${prefix}$${ordinal}${bindingName ?? ''}`,
753
+ label: isAnonymous ? 'Class' : localLabel,
754
+ ...(bindingName === undefined ? {} : { bindingName }),
755
+ };
756
+ state.byStart.set(node.startIndex, identity);
757
+ return identity;
758
+ };
759
+ exports.synthesizeJavaTypeIdentity = synthesizeJavaTypeIdentity;
760
+ const findEnclosingClassInfo = (node, filePath, resolveEnclosingOwner,
761
+ /**
762
+ * Optional (#1978): returns the enclosing type's fully-qualified name
763
+ * (e.g. "Outer.Inner") for a type-declaration container, or null. Callers
764
+ * pass `classExtractor.extractQualifiedName` ONLY when the language's
765
+ * `qualifiedNodeId` flag is on — so when omitted, behavior is byte-identical
766
+ * to before (qualifiedClassId stays undefined). Used by the standard
767
+ * class-container branch to compute `qualifiedClassId` from the SAME function
768
+ * the node-id is built from, guaranteeing owner-id == node-id by construction.
769
+ */
770
+ getQualifiedOwnerName) => {
771
+ let current = node.parent;
772
+ let iterations = 0;
773
+ // Tracks container nodes already visited via the hook so a misbehaving hook
774
+ // that keeps redirecting back to the same container cannot loop forever.
775
+ const visitedContainers = new Set();
776
+ while (current) {
777
+ if (++iterations > MAX_ENCLOSING_WALK_ITERATIONS) {
778
+ // Defense-in-depth: a real source tree has nowhere near this many ancestors.
779
+ // Bail out rather than hang ingestion.
780
+ return null;
781
+ }
782
+ // Go: method_declaration has a receiver parameter with the struct type
783
+ if (current.type === 'method_declaration') {
784
+ const receiver = current.childForFieldName?.('receiver');
785
+ if (receiver) {
786
+ const paramDecl = receiver.namedChildren?.find?.((c) => c.type === 'parameter_declaration');
787
+ if (paramDecl) {
788
+ const typeNode = paramDecl.childForFieldName?.('type');
789
+ if (typeNode) {
790
+ const inner = typeNode.type === 'pointer_type' ? typeNode.firstNamedChild : typeNode;
791
+ if (inner && (inner.type === 'type_identifier' || inner.type === 'identifier')) {
792
+ return {
793
+ classId: (0, utils_js_1.generateId)('Struct', `${filePath}:${inner.text}`),
794
+ className: inner.text,
795
+ };
796
+ }
797
+ }
798
+ }
799
+ }
800
+ }
801
+ // Go: the `type_spec` IS the declared type (`type User struct { ... }`, and
802
+ // one per member of a grouped `type ( A struct{…}; B struct{…} )` block).
803
+ //
804
+ // Matched here rather than on the enclosing `type_declaration` (#2837): this
805
+ // walk climbs `node.parent`, so it passes THROUGH the containing spec on its
806
+ // way up from any member, and the structure it already has is the answer.
807
+ // Keying on the wrapper instead meant picking one spec out of several with
808
+ // no reference point — which filed every member of a grouped block under its
809
+ // FIRST struct, so two same-named fields minted one id and first-write-wins
810
+ // dropped the second.
811
+ if (current.type === 'type_spec') {
812
+ const typeBody = current.childForFieldName?.('type');
813
+ if (typeBody?.type === 'struct_type' || typeBody?.type === 'interface_type') {
814
+ const nameNode = current.childForFieldName?.('name');
815
+ if (nameNode) {
816
+ const label = typeBody.type === 'struct_type' ? 'Struct' : 'Interface';
817
+ return {
818
+ classId: (0, utils_js_1.generateId)(label, `${filePath}:${nameNode.text}`),
819
+ className: nameNode.text,
820
+ };
821
+ }
822
+ }
823
+ }
824
+ // Java: an anonymous class body owns its members — attribute to the
825
+ // synthesized `Worker$N`/`E$N` class, not the lexically enclosing
826
+ // named type (#2550/#2555). Covers both shapes: `new Runnable() { ... }`
827
+ // and enum constant bodies (`enum E { A { ... } }`). The synthesis
828
+ // returns undefined for shape-less nodes (plain `new Foo()`, a body-less
829
+ // enum constant, and every C# `object_creation_expression`), so the
830
+ // walk continues unchanged for those — including on to
831
+ // `enum_declaration`, which sits in CLASS_CONTAINER_TYPES below.
832
+ if (isJavaAnonymousBodyNode(current) || JAVA_ANON_HOST_TYPES.has(current.type)) {
833
+ const identity = (0, exports.synthesizeJavaTypeIdentity)(current);
834
+ if (identity !== undefined) {
835
+ return {
836
+ classId: (0, utils_js_1.generateId)(identity.label, `${filePath}:${identity.name}`),
837
+ className: identity.name,
838
+ };
839
+ }
840
+ }
841
+ if (exports.CLASS_CONTAINER_TYPES.has(current.type)) {
842
+ // Delegate language-specific container remapping to the provider hook.
843
+ if (resolveEnclosingOwner) {
844
+ if (visitedContainers.has(current)) {
845
+ // We've already asked the hook about this container once — a loop
846
+ // would form (e.g., hook redirects to a child node whose parent is
847
+ // this same container). Skip and walk up.
848
+ current = current.parent;
849
+ continue;
850
+ }
851
+ visitedContainers.add(current);
852
+ const resolved = resolveEnclosingOwner(current);
853
+ if (resolved === null) {
854
+ // Provider says skip this container — keep walking up.
855
+ current = current.parent;
856
+ continue;
857
+ }
858
+ if (resolved !== current) {
859
+ // Provider remapped to a different node — re-evaluate from there.
860
+ current = resolved;
861
+ continue;
862
+ }
863
+ }
864
+ // Rust impl_item: for `impl Trait for Struct {}`, pick the type after `for`
865
+ // NOTE: This impl_item ownership logic is mirrored in
866
+ // method-extractors/configs/rust.ts (extractOwnerName, metadata only).
867
+ if (current.type === 'impl_item') {
868
+ const children = current.children ?? [];
869
+ const forIdx = children.findIndex((c) => c.text === 'for');
870
+ if (forIdx !== -1) {
871
+ const nameNode = children
872
+ .slice(forIdx + 1)
873
+ .find((c) => c.type === 'type_identifier' ||
874
+ c.type === 'scoped_type_identifier' ||
875
+ c.type === 'identifier');
876
+ if (nameNode) {
877
+ // `for` target keeps its raw text. A scoped path (impl T for a::Inner)
878
+ // therefore owns through `a::Inner`, which only resolves once the
879
+ // referenced struct is keyed by its qualified path — deferred to #1978.
880
+ return {
881
+ classId: (0, utils_js_1.generateId)('Struct', `${filePath}:${nameNode.text}`),
882
+ className: nameNode.text,
883
+ };
884
+ }
885
+ }
886
+ // Inherent impl target.
887
+ // - SCOPED (`impl a::Inner`, scoped_type_identifier): key by FULL text,
888
+ // matching the @definition.impl scoped arm (#1975). UNCHANGED.
889
+ // - UNSCOPED (`impl Inner`, type_identifier): qualify by the enclosing
890
+ // `mod_item` scope (`outer.Inner`) so two same-tail bare impls under
891
+ // different mods own through DISTINCT nodes. The Impl-node
892
+ // materialization (parsing-processor / parse-worker) mirrors this, so
893
+ // the owner id == the Impl node id byte-for-byte (#1982).
894
+ // - GENERIC (`impl<T> Inner<T>`, generic_type): the @definition.impl
895
+ // node is materialized only when the generic base is a bare
896
+ // `type_identifier` (tree-sitter-queries.ts), qualified the same way —
897
+ // so drill into the base and mirror that gate, keeping the owner id ==
898
+ // the node id byte-for-byte (#1992). A generic over a SCOPED base
899
+ // (`impl<T> a::Inner<T>`) materializes NO node, so it must produce NO
900
+ // owner (the method orphans — scoped-generic deferred, #1992).
901
+ const implTarget = children.find((c) => c.type === 'type_identifier' ||
902
+ c.type === 'scoped_type_identifier' ||
903
+ c.type === 'generic_type');
904
+ if (implTarget) {
905
+ const baseType = implTarget.type === 'generic_type'
906
+ ? (implTarget.childForFieldName?.('type') ?? null)
907
+ : implTarget;
908
+ if (baseType?.type === 'type_identifier') {
909
+ // Bare target (`impl Inner` or `impl<T> Inner<T>`): qualify by mod scope.
910
+ // #1992 follow-up: qualify `className` too (not just `classId`). The
911
+ // method node id is keyed `${className}.${name}`, so a bare tail collapses
912
+ // two same-tail bare impls that ALSO share a method name (`a::Inner::m` +
913
+ // `b::Inner::m` both → `Inner.m`) onto one Method node (graph addNode is
914
+ // first-write-wins). Qualifying className → `a.Inner.m` / `b.Inner.m` keeps
915
+ // them distinct. Symmetric: the call-resolution fallback rebuilds the same
916
+ // `${className}.${name}` from the same enclosing-impl walk, so def and call
917
+ // ids still agree. Owner edge anchors on `classId` (already qualified).
918
+ const qualified = (0, exports.qualifyRustImplTargetByModScope)(current, baseType.text);
919
+ return {
920
+ classId: (0, utils_js_1.generateId)('Impl', `${filePath}:${qualified}`),
921
+ className: qualified,
922
+ };
923
+ }
924
+ if (baseType?.type === 'scoped_type_identifier' && implTarget.type !== 'generic_type') {
925
+ // Top-level scoped `impl a::Inner`: key by full raw text (#1975).
926
+ return {
927
+ classId: (0, utils_js_1.generateId)('Impl', `${filePath}:${baseType.text}`),
928
+ className: baseType.text,
929
+ };
930
+ }
931
+ // generic-over-scoped (`impl<T> a::Inner<T>`) and any other base: fall
932
+ // through with no owner — no @definition.impl node exists, so attributing
933
+ // a method to a synthesized id would orphan it against a phantom owner.
934
+ }
935
+ }
936
+ const nameNode = current.childForFieldName?.('name') ??
937
+ current.children?.find((c) => c.type === 'type_identifier' ||
938
+ c.type === 'identifier' ||
939
+ c.type === 'name' ||
940
+ c.type === 'constant');
941
+ if (nameNode) {
942
+ let label = exports.CONTAINER_TYPE_TO_LABEL[current.type] || 'Class';
943
+ // Kotlin: class_declaration with an anonymous "interface" keyword child
944
+ // is actually an interface, not a class. Refine the label to match the
945
+ // node ID generated from the tree-sitter query capture (@definition.interface).
946
+ if (current.type === 'class_declaration' &&
947
+ label === 'Class' &&
948
+ current.children?.some((c) => c.type === 'interface')) {
949
+ label = 'Interface';
950
+ }
951
+ // class_declaration with a `declaration_kind` field collapses several
952
+ // type kinds onto one node (tree-sitter-swift: class / struct / enum /
953
+ // extension / actor). The structure query labels struct → Struct and
954
+ // enum → Enum; refine the owner label to match so a member edge
955
+ // (HAS_METHOD / HAS_PROPERTY) anchors on the real Enum/Struct node id
956
+ // rather than a non-existent `Class:` id (F79). Gated on the field
957
+ // being present, so it is a no-op for grammars whose class_declaration
958
+ // has no `declaration_kind` field (e.g. Kotlin).
959
+ if (current.type === 'class_declaration' && label === 'Class') {
960
+ const declKind = current.childForFieldName?.('declaration_kind')?.text;
961
+ if (declKind === 'struct')
962
+ label = 'Struct';
963
+ else if (declKind === 'enum')
964
+ label = 'Enum';
965
+ }
966
+ const templateArguments = (0, template_arguments_js_1.extractTemplateArguments)(nameNode.text);
967
+ const classIdName = templateArguments !== undefined
968
+ ? `${(0, template_arguments_js_1.stripTemplateArguments)(nameNode.text)}${(0, template_arguments_js_1.templateArgumentsIdTag)(templateArguments)}`
969
+ : nameNode.text;
970
+ // #1978: when the language opts into qualified node ids, key the owner
971
+ // edge by the enclosing type's qualified path (e.g. "Outer.Inner") so it
972
+ // matches the qualified class node id. Derived from the SAME
973
+ // extractQualifiedName the node-id uses → agree by construction. Only set
974
+ // when actually nested (qualified !== simple); top-level types are
975
+ // unchanged. (Go receiver / Rust impl branches return earlier and are
976
+ // intentionally untouched here.)
977
+ const qualifiedOwnerName = getQualifiedOwnerName?.(current, nameNode.text);
978
+ const qualifiedClassId = qualifiedOwnerName != null && qualifiedOwnerName !== nameNode.text
979
+ ? (0, utils_js_1.generateId)(label, `${filePath}:${templateArguments !== undefined
980
+ ? `${(0, template_arguments_js_1.stripTemplateArguments)(qualifiedOwnerName)}${(0, template_arguments_js_1.templateArgumentsIdTag)(templateArguments)}`
981
+ : qualifiedOwnerName}`)
982
+ : undefined;
983
+ return {
984
+ classId: (0, utils_js_1.generateId)(label, `${filePath}:${classIdName}`),
985
+ className: nameNode.text,
986
+ ...(qualifiedClassId !== undefined ? { qualifiedClassId } : {}),
987
+ };
988
+ }
989
+ }
990
+ current = current.parent;
991
+ }
992
+ return null;
993
+ };
994
+ exports.findEnclosingClassInfo = findEnclosingClassInfo;
995
+ /**
996
+ * Block-statement AST types that disqualify an object-literal binding from
997
+ * carrying a HAS_METHOD edge. A `const` declared inside one of these is block-
998
+ * scoped and cannot be imported, so attributing methods to it would create
999
+ * false-positive cross-file edges.
1000
+ */
1001
+ const BLOCK_SCOPE_BOUNDARY_TYPES = new Set([
1002
+ 'statement_block',
1003
+ 'if_statement',
1004
+ 'else_clause',
1005
+ 'for_statement',
1006
+ 'for_in_statement',
1007
+ 'for_of_statement',
1008
+ 'while_statement',
1009
+ 'do_statement',
1010
+ 'try_statement',
1011
+ 'catch_clause',
1012
+ 'finally_clause',
1013
+ 'switch_statement',
1014
+ 'switch_case',
1015
+ 'switch_default',
1016
+ 'with_statement',
1017
+ ]);
1018
+ /**
1019
+ * Find the file-scope variable that owns an object literal method definition.
1020
+ *
1021
+ * Covers TypeScript/JavaScript shorthand object methods such as:
1022
+ *
1023
+ * export const service = { async load() {} };
1024
+ *
1025
+ * tree-sitter represents `load` as a `method_definition` inside an `object`,
1026
+ * not inside a class container. Without this fallback, ingestion emits a
1027
+ * top-level `Method` node but no edge from the exported `service` value to
1028
+ * that method, so impact queries cannot discover `service.load`.
1029
+ *
1030
+ * Two-phase walk:
1031
+ * Phase A walks up from `node` tracking how many `object` ancestors we
1032
+ * cross. The first `variable_declarator` reached with `objectDepth >= 1`
1033
+ * is the candidate owner — unless `objectDepth > 1` (the method belongs
1034
+ * to a nested object literal; we return null rather than misattribute
1035
+ * to the outer binding). Hitting a function/class container before the
1036
+ * declarator returns null (catches IIFE-wrapped literals).
1037
+ * Phase B walks the declarator's own ancestors. Any function or class
1038
+ * ancestor before reaching `program`/`export_statement` returns null
1039
+ * (catches `const` declared inside a function body). Any block-statement
1040
+ * ancestor also returns null (catches block-scoped declarations inside
1041
+ * top-level `if`/`for`/`try`/etc., which cannot be imported).
1042
+ */
1043
+ const findObjectLiteralBindingInfo = (node, filePath) => {
1044
+ // ── Phase A: walk up from node, count `object` ancestors, find declarator
1045
+ let current = node;
1046
+ let objectDepth = 0;
1047
+ let declarator = null;
1048
+ while (current) {
1049
+ if (current.type === 'object') {
1050
+ objectDepth += 1;
1051
+ }
1052
+ if (current.type === 'variable_declarator' && objectDepth >= 1) {
1053
+ if (objectDepth > 1) {
1054
+ // Method belongs to a nested object literal; safe under-approximation.
1055
+ return null;
1056
+ }
1057
+ declarator = current;
1058
+ break;
1059
+ }
1060
+ if (current !== node &&
1061
+ (exports.FUNCTION_NODE_TYPES.has(current.type) || exports.CLASS_CONTAINER_TYPES.has(current.type))) {
1062
+ // Function/class container encountered before owning declarator
1063
+ // (e.g. IIFE-wrapped object literal). Bail out.
1064
+ return null;
1065
+ }
1066
+ current = current.parent;
1067
+ }
1068
+ if (!declarator)
1069
+ return null;
1070
+ // ── Phase B: declarator must live at file scope (program / export_statement)
1071
+ // with no function, class, or block-statement ancestor in between.
1072
+ let anc = declarator.parent;
1073
+ while (anc) {
1074
+ if (anc.type === 'program' || anc.type === 'export_statement') {
1075
+ break;
1076
+ }
1077
+ if (exports.FUNCTION_NODE_TYPES.has(anc.type) || exports.CLASS_CONTAINER_TYPES.has(anc.type)) {
1078
+ return null;
1079
+ }
1080
+ if (BLOCK_SCOPE_BOUNDARY_TYPES.has(anc.type)) {
1081
+ return null;
1082
+ }
1083
+ anc = anc.parent;
1084
+ }
1085
+ const nameNode = declarator.childForFieldName?.('name');
1086
+ if (!nameNode || nameNode.type !== 'identifier')
1087
+ return null;
1088
+ const declaration = declarator.parent;
1089
+ const ownerLabel = declaration?.type === 'variable_declaration' ? 'Variable' : 'Const';
1090
+ return {
1091
+ ownerId: (0, utils_js_1.generateId)(ownerLabel, `${filePath}:${nameNode.text}`),
1092
+ };
1093
+ };
1094
+ exports.findObjectLiteralBindingInfo = findObjectLiteralBindingInfo;
1095
+ /**
1096
+ * Find the owner of a member assigned by `<Owner>.prototype.<member> = fn`
1097
+ * (#2723 follow-up).
1098
+ *
1099
+ * Sibling of {@link findObjectLiteralBindingInfo}: same seam, same return
1100
+ * shape, different syntax. There the owner is the variable the literal is
1101
+ * bound to; here it is the identifier to the left of `.prototype`.
1102
+ *
1103
+ * The owner label is read from the file's own module-scope declaration, so the
1104
+ * edge points at the node that actually exists — `function Foo() {}` is a
1105
+ * `Function` node, `class Foo {}` is a `Class` node. When the file declares no
1106
+ * such name (the constructor lives in another module) no owner is claimed:
1107
+ * a HAS_METHOD edge to a fabricated node is worse than a top-level Method.
1108
+ */
1109
+ const findMemberAssignmentOwnerInfo = (node, filePath) => {
1110
+ const ownerName = (0, exports.prototypeAssignmentOwnerName)(node) ?? (0, exports.thisAssignmentOwnerName)(node);
1111
+ if (ownerName === null)
1112
+ return null;
1113
+ const root = node.tree?.rootNode;
1114
+ if (!root)
1115
+ return null;
1116
+ const ownerLabel = prototypeOwnerLabel(root, ownerName);
1117
+ if (ownerLabel === null)
1118
+ return null;
1119
+ return { ownerId: (0, utils_js_1.generateId)(ownerLabel, `${filePath}:${ownerName}`), ownerName };
1120
+ };
1121
+ exports.findMemberAssignmentOwnerInfo = findMemberAssignmentOwnerInfo;
1122
+ /** Right-hand-side node types that make an assignment a callable binding. */
1123
+ const CALLABLE_ASSIGNMENT_VALUE_TYPES = new Set([
1124
+ 'arrow_function',
1125
+ 'function_expression',
1126
+ 'generator_function',
1127
+ ]);
1128
+ /**
1129
+ * The receiver name of a `<Owner>.prototype.<member> = <function>` assignment,
1130
+ * or null when `assignment` is not that shape.
1131
+ *
1132
+ * Only a bare identifier owner is accepted. `a.b.prototype.c = …` and
1133
+ * `getClass().prototype.c = …` name an owner this layer cannot resolve to a
1134
+ * definition, so they are left alone rather than attributed to a guess.
1135
+ */
1136
+ const prototypeAssignmentOwnerName = (assignment) => {
1137
+ const left = callableAssignmentTarget(assignment);
1138
+ if (left === null)
1139
+ return null;
1140
+ const protoRef = left.childForFieldName('object');
1141
+ if (protoRef === null || protoRef.type !== 'member_expression')
1142
+ return null;
1143
+ if (protoRef.childForFieldName('property')?.text !== 'prototype')
1144
+ return null;
1145
+ const owner = protoRef.childForFieldName('object');
1146
+ if (owner === null || owner.type !== 'identifier')
1147
+ return null;
1148
+ return owner.text;
1149
+ };
1150
+ exports.prototypeAssignmentOwnerName = prototypeAssignmentOwnerName;
1151
+ /** The `member_expression` being assigned a function value, or null. */
1152
+ const callableAssignmentTarget = (assignment) => {
1153
+ if (assignment.type !== 'assignment_expression')
1154
+ return null;
1155
+ const right = assignment.childForFieldName('right');
1156
+ if (right === null || !CALLABLE_ASSIGNMENT_VALUE_TYPES.has(right.type))
1157
+ return null;
1158
+ const left = assignment.childForFieldName('left');
1159
+ return left !== null && left.type === 'member_expression' ? left : null;
1160
+ };
1161
+ /**
1162
+ * The constructor function that owns a `this.member = <function>` assignment,
1163
+ * or null when there is none (module top level, or an owner this layer cannot
1164
+ * name).
1165
+ *
1166
+ * Only a `function_declaration` counts. An `arrow_function` does NOT bind its
1167
+ * own `this` (ECMA-262 gives it `[[ThisMode]] = lexical`), so the walk passes
1168
+ * through arrows to the function that actually binds the receiver — the same
1169
+ * rule `@receiver-owner.this` encodes in the scope queries (#2701). A class
1170
+ * method never reaches here: parse-worker resolves its owner from the
1171
+ * enclosing class container first.
1172
+ */
1173
+ const thisAssignmentOwnerName = (assignment) => {
1174
+ const left = callableAssignmentTarget(assignment);
1175
+ if (left === null)
1176
+ return null;
1177
+ if (left.childForFieldName('object')?.type !== 'this')
1178
+ return null;
1179
+ for (let anc = assignment.parent; anc !== null; anc = anc.parent) {
1180
+ if (anc.type === 'arrow_function')
1181
+ continue;
1182
+ if (anc.type === 'function_declaration') {
1183
+ const name = anc.childForFieldName('name');
1184
+ return name !== null && name.type === 'identifier' ? name.text : null;
1185
+ }
1186
+ // Any other receiver-binding form (function_expression, method_definition,
1187
+ // generator) owns the `this` but gives this layer no module-scope name to
1188
+ // point an owner edge at.
1189
+ if (exports.FUNCTION_NODE_TYPES.has(anc.type) || exports.CLASS_CONTAINER_TYPES.has(anc.type))
1190
+ return null;
1191
+ }
1192
+ return null;
1193
+ };
1194
+ exports.thisAssignmentOwnerName = thisAssignmentOwnerName;
1195
+ /**
1196
+ * True when `node` is a `X.prototype.Y = <function>` or `this.Y = <function>`
1197
+ * assignment — i.e. a callable MEMBER rather than a free function.
1198
+ *
1199
+ * Takes the ASSIGNMENT node, because that is what the `@definition.function`
1200
+ * capture is anchored on and therefore what `provider.labelOverride` receives.
1201
+ */
1202
+ const isPrototypeMemberAssignmentNode = (node) => (0, exports.prototypeAssignmentOwnerName)(node) !== null || (0, exports.isThisMemberAssignmentNode)(node);
1203
+ exports.isPrototypeMemberAssignmentNode = isPrototypeMemberAssignmentNode;
1204
+ /**
1205
+ * True when `node` is `module.exports = <anonymous function>` (#2723).
1206
+ *
1207
+ * The whole module IS the callable, so there is no property to take a name
1208
+ * from and the caller supplies a file-derived one. A NAMED function expression
1209
+ * is excluded — its own name is captured directly and is more informative.
1210
+ */
1211
+ /**
1212
+ * True when `node` is `module.exports = <function>`, named or anonymous — the
1213
+ * CommonJS default export, where the whole module IS the callable.
1214
+ *
1215
+ * `exports = fn` is deliberately NOT this shape: reassigning the `exports`
1216
+ * binding does not export anything in CommonJS, it only breaks the alias to
1217
+ * `module.exports`.
1218
+ */
1219
+ const isCjsDefaultExportAssignment = (node) => {
1220
+ if (node.type !== 'assignment_expression')
1221
+ return false;
1222
+ const right = node.childForFieldName('right');
1223
+ if (right === null || !CALLABLE_ASSIGNMENT_VALUE_TYPES.has(right.type))
1224
+ return false;
1225
+ const left = node.childForFieldName('left');
1226
+ if (left === null || left.type !== 'member_expression')
1227
+ return false;
1228
+ return (left.childForFieldName('object')?.text === 'module' &&
1229
+ left.childForFieldName('property')?.text === 'exports');
1230
+ };
1231
+ exports.isCjsDefaultExportAssignment = isCjsDefaultExportAssignment;
1232
+ /** True when `node` is a `this.Y = <function>` assignment, at any nesting. */
1233
+ const isThisMemberAssignmentNode = (node) => {
1234
+ const left = callableAssignmentTarget(node);
1235
+ return left !== null && left.childForFieldName('object')?.type === 'this';
1236
+ };
1237
+ exports.isThisMemberAssignmentNode = isThisMemberAssignmentNode;
1238
+ /**
1239
+ * The label the owner named by {@link prototypeAssignmentOwnerName} carries in
1240
+ * the graph, so the owner edge points at the node that actually exists.
1241
+ * Returns null when the file declares no such module-scope name.
1242
+ */
1243
+ const prototypeOwnerLabel = (root, ownerName) => {
1244
+ for (const child of root.namedChildren) {
1245
+ const decl = child.type === 'export_statement' ? child.childForFieldName('declaration') : child;
1246
+ if (decl === null)
1247
+ continue;
1248
+ if (decl.childForFieldName('name')?.text === ownerName) {
1249
+ if (decl.type === 'class_declaration')
1250
+ return 'Class';
1251
+ if (decl.type === 'function_declaration' || decl.type === 'generator_function_declaration')
1252
+ return 'Function';
1253
+ }
1254
+ // `var Foo = function () {}` / `const Foo = () => {}` / `const Foo = class {}`.
1255
+ // The dominant pre-ES6 constructor form, and the population this whole
1256
+ // change targets. Without it `prototypeOwnerLabel` returned null, the
1257
+ // member fell back to an UNQUALIFIED `Method:<file>:<member>` id, and two
1258
+ // constructors defining the same member name in one file collapsed onto a
1259
+ // single node with no owner edges at all (#2729 review F6).
1260
+ if (!VARIABLE_DECLARATION_NODE_TYPES.has(decl.type))
1261
+ continue;
1262
+ for (const declarator of decl.namedChildren) {
1263
+ if (declarator.type !== 'variable_declarator')
1264
+ continue;
1265
+ if (declarator.childForFieldName('name')?.text !== ownerName)
1266
+ continue;
1267
+ const value = declarator.childForFieldName('value');
1268
+ if (value === null)
1269
+ continue;
1270
+ // Only a callable value is claimed. A closure binding reliably emits
1271
+ // `Function:<file>:<name>` (the #2687/#2693 convention), so the owner id
1272
+ // resolves to a node that exists. A class EXPRESSION or a require()-bound
1273
+ // value names an owner whose node label this layer cannot predict —
1274
+ // claim none rather than point an edge at a node that may not exist,
1275
+ // which is the same defect class this fix exists to remove.
1276
+ if (CALLABLE_ASSIGNMENT_VALUE_TYPES.has(value.type))
1277
+ return 'Function';
1278
+ }
1279
+ }
1280
+ return null;
1281
+ };
1282
+ /** Declaration nodes carrying `variable_declarator` children (JS/TS). */
1283
+ const VARIABLE_DECLARATION_NODE_TYPES = new Set([
1284
+ 'lexical_declaration',
1285
+ 'variable_declaration',
1286
+ ]);
1287
+ /** Convenience wrapper: returns just the class ID string (backward compat). */
1288
+ const findEnclosingClassId = (node, filePath) => {
1289
+ return (0, exports.findEnclosingClassInfo)(node, filePath)?.classId ?? null;
1290
+ };
1291
+ exports.findEnclosingClassId = findEnclosingClassId;
1292
+ /**
1293
+ * Find a child of `childType` within a sibling node of `siblingType`.
1294
+ * Used for Kotlin AST traversal where visibility_modifier lives inside a modifiers sibling.
1295
+ */
1296
+ const findSiblingChild = (parent, siblingType, childType) => {
1297
+ for (let i = 0; i < parent.childCount; i++) {
1298
+ const sibling = parent.child(i);
1299
+ if (sibling?.type === siblingType) {
1300
+ for (let j = 0; j < sibling.childCount; j++) {
1301
+ const child = sibling.child(j);
1302
+ if (child?.type === childType)
1303
+ return child;
1304
+ }
1305
+ }
1306
+ }
1307
+ return null;
1308
+ };
1309
+ exports.findSiblingChild = findSiblingChild;
1310
+ /** Generic name extraction from a function-like AST node.
1311
+ * Tries `node.childForFieldName('name')?.text`, then scans children for
1312
+ * `identifier` / `property_identifier` / `simple_identifier`.
1313
+ *
1314
+ * `arrow_function` and `function_expression` (TS/JS) are inherently
1315
+ * anonymous — they have no `name` field, and their first identifier
1316
+ * child is a *parameter*, not a function name. Returning a parameter
1317
+ * identifier here would synthesize phantom Function IDs (e.g. callers
1318
+ * walking up from a call inside `arr.map(x => fn(x))` would get
1319
+ * attributed to a non-existent "Function x"). The language's
1320
+ * `methodExtractor.extractFunctionName` hook is responsible for naming
1321
+ * these via parent context (variable_declarator, pair, etc.); when it
1322
+ * declines, the parent walk should continue rather than fall through
1323
+ * here. See issue #1166. */
1324
+ const genericFuncName = (node) => {
1325
+ const nameField = node.childForFieldName?.('name');
1326
+ if (nameField)
1327
+ return nameField.text;
1328
+ if (node.type === 'arrow_function' || node.type === 'function_expression') {
1329
+ return null;
1330
+ }
1331
+ for (let i = 0; i < node.childCount; i++) {
1332
+ const c = node.child(i);
1333
+ if (c?.type === 'identifier' ||
1334
+ c?.type === 'property_identifier' ||
1335
+ c?.type === 'simple_identifier')
1336
+ return c.text;
1337
+ }
1338
+ return null;
1339
+ };
1340
+ exports.genericFuncName = genericFuncName;
1341
+ /** AST node types that represent a method definition (for `inferFunctionLabel`). */
1342
+ exports.METHOD_LABEL_NODE_TYPES = new Set([
1343
+ 'method_definition',
1344
+ 'method_declaration',
1345
+ 'method',
1346
+ 'singleton_method',
1347
+ ]);
1348
+ /** AST node types that represent a constructor definition (for `inferFunctionLabel`). */
1349
+ exports.CONSTRUCTOR_LABEL_NODE_TYPES = new Set([
1350
+ 'constructor_declaration',
1351
+ 'compact_constructor_declaration',
1352
+ ]);
1353
+ /** Infer node label from AST node type for function-like nodes without a provider hook. */
1354
+ const inferFunctionLabel = (nodeType) => exports.METHOD_LABEL_NODE_TYPES.has(nodeType)
1355
+ ? 'Method'
1356
+ : exports.CONSTRUCTOR_LABEL_NODE_TYPES.has(nodeType)
1357
+ ? 'Constructor'
1358
+ : 'Function';
1359
+ exports.inferFunctionLabel = inferFunctionLabel;
1360
+ /** Argument list node types shared between countCallArguments and call-resolution helpers. */
1361
+ exports.CALL_ARGUMENT_LIST_TYPES = new Set(['arguments', 'argument_list', 'value_arguments']);
1362
+ /**
1363
+ * Function/method parameter-list node types across grammars. Used to tell a
1364
+ * PARAMETER-property (a constructor parameter that is also a class field, e.g.
1365
+ * TypeScript `constructor(public name: string)`) apart from a function-BODY
1366
+ * local: a property reached through one of these — rather than through the
1367
+ * function's executable body — is a genuine class member, so the
1368
+ * function-local-property guard must NOT strip its owner edge.
1369
+ */
1370
+ exports.PARAMETER_LIST_NODE_TYPES = new Set([
1371
+ 'formal_parameters', // TypeScript / JavaScript
1372
+ 'parameters', // Python / C#
1373
+ 'parameter_list', // Java / Go / C / Swift
1374
+ 'function_value_parameters', // Kotlin
1375
+ 'class_parameters', // Scala-like / future grammars
1376
+ ]);
1377
+ /**
1378
+ * Executable local-scope boundaries for the property-ownership guard
1379
+ * (`isFunctionLocalProperty` in parse-worker.ts). A `Property` capture whose
1380
+ * nearest enclosing scope — walking up before any class container — is one of
1381
+ * these executable bodies is a function-local binding, NOT a class member, so it
1382
+ * must not receive a class `HAS_PROPERTY` owner edge.
1383
+ *
1384
+ * Derived from FUNCTION_NODE_TYPES, with two deliberate adjustments found by the
1385
+ * #1919 review of the original guard:
1386
+ * - EXCLUDES Dart's bare signature wrappers (`function_signature` /
1387
+ * `method_signature`). A Dart getter/setter NAME lives under `method_signature`,
1388
+ * yet it is a class-member declaration, not a local inside an executable body;
1389
+ * treating the signature as a scope boundary OVER-stripped every Dart class
1390
+ * accessor's owner edge. (Signatures are Dart-only; no language emits a
1391
+ * legitimately-function-local Property under one.)
1392
+ * - INCLUDES accessor + initializer bodies (Kotlin `anonymous_initializer` /
1393
+ * `getter` / `setter`, Swift `computed_property` / `computed_getter` /
1394
+ * `computed_setter` / `computed_modify`). Destructuring/locals inside these ARE
1395
+ * function-local, yet they are absent from FUNCTION_NODE_TYPES; omitting them
1396
+ * UNDER-stripped and emitted spurious class `HAS_PROPERTY` edges for
1397
+ * `init {}` / accessor-body destructuring bindings.
1398
+ *
1399
+ * Kept separate from FUNCTION_NODE_TYPES because that set has many other consumers
1400
+ * (e.g. enclosing-callable resolution) where signatures must remain function nodes
1401
+ * and accessor bodies must not.
1402
+ */
1403
+ exports.LOCAL_SCOPE_BODY_NODE_TYPES = new Set([...exports.FUNCTION_NODE_TYPES]
1404
+ .filter((t) => t !== 'function_signature' && t !== 'method_signature')
1405
+ .concat([
1406
+ 'anonymous_initializer', // Kotlin: init { }
1407
+ 'getter', // Kotlin: val x get() { }
1408
+ 'setter', // Kotlin: var x set(v) { }
1409
+ 'computed_property', // Swift: var x: T { get set }
1410
+ 'computed_getter', // Swift: get { }
1411
+ 'computed_setter', // Swift: set { }
1412
+ 'computed_modify', // Swift: _modify { }
1413
+ ]));
1414
+ /**
1415
+ * Callable node types whose grammar splits the body off into a SIBLING node, so
1416
+ * the callable is never an ancestor of the code inside it (Dart
1417
+ * `function_signature` / `method_signature`).
1418
+ *
1419
+ * Derived, not listed, so it cannot drift from the two sets that define it:
1420
+ * `LOCAL_SCOPE_BODY_NODE_TYPES` is `FUNCTION_NODE_TYPES` minus exactly the bare
1421
+ * signature types, so the difference IS the split-signature set.
1422
+ *
1423
+ * Must stay BELOW `LOCAL_SCOPE_BODY_NODE_TYPES` — reading it earlier hits the
1424
+ * temporal dead zone and throws at module load.
1425
+ */
1426
+ exports.SPLIT_SIGNATURE_NODE_TYPES = new Set([...exports.FUNCTION_NODE_TYPES].filter((t) => !exports.LOCAL_SCOPE_BODY_NODE_TYPES.has(t)));
1427
+ // ============================================================================
1428
+ // Generic AST traversal helpers (shared by parse-worker + php-helpers)
1429
+ // ============================================================================
1430
+ /** Walk an AST node depth-first, returning the first descendant with the given type. */
1431
+ function findDescendant(root, type) {
1432
+ const stack = [root];
1433
+ while (stack.length > 0) {
1434
+ const node = stack.pop();
1435
+ if (node.type === type)
1436
+ return node;
1437
+ // Push in reverse order so left children are visited first (depth-first)
1438
+ const children = node.children ?? [];
1439
+ for (let i = children.length - 1; i >= 0; i--) {
1440
+ stack.push(children[i]);
1441
+ }
1442
+ }
1443
+ return null;
1444
+ }
1445
+ /** Extract the text content from a string or encapsed_string AST node. */
1446
+ function extractStringContent(node) {
1447
+ if (!node)
1448
+ return null;
1449
+ const content = node.children?.find((c) => c.type === 'string_content');
1450
+ if (content)
1451
+ return content.text;
1452
+ if (node.type === 'string_content')
1453
+ return node.text;
1454
+ return null;
1455
+ }
1456
+ /** Find the first direct named child of a tree-sitter node matching the given type. */
1457
+ function findChild(node, type) {
1458
+ for (let i = 0; i < node.namedChildCount; i++) {
1459
+ const child = node.namedChild(i);
1460
+ if (child?.type === type)
1461
+ return child;
1462
+ }
1463
+ return null;
1464
+ }
1465
+ /** Remove bidi-override and zero-width control characters from attacker-
1466
+ * influenced repository text before it is exposed through graph descriptions
1467
+ * or MCP output (#2286). Global `sanitizeUTF8` intentionally remains focused
1468
+ * on encoding/control-character validity. */
1469
+ const stripBidiAndZeroWidth = (text) => Array.from(text)
1470
+ .filter((ch) => {
1471
+ const c = ch.codePointAt(0) ?? 0;
1472
+ // Bidi overrides/isolates (U+202A–202E, U+2066–2069), zero-width
1473
+ // space/joiners (U+200B–200D), and BOM/zero-width-no-break (U+FEFF).
1474
+ return !((c >= 0x202a && c <= 0x202e) ||
1475
+ (c >= 0x2066 && c <= 0x2069) ||
1476
+ (c >= 0x200b && c <= 0x200d) ||
1477
+ c === 0xfeff);
1478
+ })
1479
+ .join('');
1480
+ exports.stripBidiAndZeroWidth = stripBidiAndZeroWidth;
1481
+ /** Normalize a block doc comment body: strip the opening (double-star or
1482
+ * bang) delimiter, the closing delimiter, and per-line gutter stars, then
1483
+ * collapse whitespace so tag content stays as searchable words. */
1484
+ const normalizeBlockDocComment = (text) => {
1485
+ const inner = (0, exports.stripBidiAndZeroWidth)(text
1486
+ .replace(/^\/\*[*!]/, '')
1487
+ // Close delimiter: tolerate the degenerate empty comment `/**/`, where the
1488
+ // opening strip already consumed the shared `*`, leaving a lone `/`.
1489
+ .replace(/\*?\/\s*$/, '')
1490
+ .replace(/^[ \t]*\*[ \t]?/gm, ' ')
1491
+ .replace(/\s+/g, ' ')
1492
+ .trim());
1493
+ return inner.length > 0 ? inner : undefined;
1494
+ };
1495
+ /** Default line-comment prefixes treated as documentation: the universal
1496
+ * triple-slash / bang-slash doc markers (Rust, C#, Dart, Swift, Doxygen).
1497
+ * Go (`//`) and Ruby (`#`) opt into their conventional markers explicitly. */
1498
+ const DEFAULT_LINE_DOC_PREFIXES = ['///', '//!'];
1499
+ /** Default block-comment doc openers: Javadoc/JSDoc-style `/**` and Doxygen
1500
+ * `/*!`. Rust opts out of `/*!` (and `//!`) because those are *inner* docs that
1501
+ * document the enclosing item, not the following one. */
1502
+ const DEFAULT_BLOCK_DOC_PREFIXES = ['/**', '/*!'];
1503
+ /** A file-top `/** … *\/` license/copyright/file-overview block has no
1504
+ * package/import sibling to shield it, so it would otherwise be absorbed as the
1505
+ * first declaration's description (PR #2286 review). These markers identify such
1506
+ * headers; they are specific enough not to fire on an ordinary symbol doc that
1507
+ * merely mentions the word "copyright". `@file`/`@fileoverview` are explicitly
1508
+ * file-level JSDoc tags, so a block carrying them is not a symbol doc. */
1509
+ const FILE_HEADER_MARKER = /SPDX-License-Identifier|@licen[sc]e\b|@fileoverview\b|@file\b|Licen[sc]ed under|copyright\s*(\(c\)|©|\d{4})/i;
1510
+ function extractLeadingDocComment(node, opts = {}) {
1511
+ const lineCommentPrefixes = opts.lineCommentPrefixes ?? DEFAULT_LINE_DOC_PREFIXES;
1512
+ const wrapperNodeTypes = opts.wrapperNodeTypes ?? [];
1513
+ const lineDirectivePrefixes = opts.lineDirectivePrefixes ?? [];
1514
+ const blockDocPrefixes = opts.blockDocPrefixes ?? DEFAULT_BLOCK_DOC_PREFIXES;
1515
+ const fromNode = (anchor) => {
1516
+ const prev = anchor.previousNamedSibling;
1517
+ if (!prev)
1518
+ return undefined;
1519
+ // Block doc comment: /** ... */ or /*! ... */
1520
+ if (blockDocPrefixes.some((p) => prev.text.startsWith(p))) {
1521
+ // Skip a file-top license/copyright/overview header (no package/import
1522
+ // sibling shields it from the first declaration). A strict row-adjacency
1523
+ // check is unreliable here — some grammars fold the trailing newline into
1524
+ // the comment node — so match header markers instead.
1525
+ if (FILE_HEADER_MARKER.test(prev.text))
1526
+ return undefined;
1527
+ return normalizeBlockDocComment(prev.text);
1528
+ }
1529
+ // Run of row-adjacent preceding line doc comments (e.g. `///` or `//`).
1530
+ const matchedPrefix = (text) => lineCommentPrefixes.find((prefix) => text.trimStart().startsWith(prefix));
1531
+ const isDirective = (text) => lineDirectivePrefixes.some((prefix) => text.trimStart().startsWith(prefix));
1532
+ const lines = [];
1533
+ let current = prev;
1534
+ let expectedRow = anchor.startPosition.row - 1;
1535
+ while (current) {
1536
+ const text = current.text;
1537
+ const prefix = matchedPrefix(text);
1538
+ if (prefix === undefined || current.startPosition.row !== expectedRow)
1539
+ break;
1540
+ // A build/tool directive or magic comment (e.g. `//go:build`,
1541
+ // `# frozen_string_literal:`) is not documentation: skip it but keep
1542
+ // walking the adjacent run, so a real doc above it is still collected.
1543
+ if (!isDirective(text))
1544
+ lines.unshift(text.trimStart().slice(prefix.length));
1545
+ expectedRow = current.startPosition.row - 1;
1546
+ current = current.previousNamedSibling;
1547
+ }
1548
+ const joined = (0, exports.stripBidiAndZeroWidth)(lines.join(' ').replace(/\s+/g, ' ').trim());
1549
+ return joined.length > 0 ? joined : undefined;
1550
+ };
1551
+ const direct = fromNode(node);
1552
+ if (direct !== undefined)
1553
+ return direct;
1554
+ const parent = node.parent;
1555
+ if (parent && wrapperNodeTypes.includes(parent.type)) {
1556
+ return fromNode(parent);
1557
+ }
1558
+ return undefined;
1559
+ }
1560
+ /** Node labels that can carry a leading doc comment — callables and type-like
1561
+ * declarations. Field/property/variable/const doc is intentionally excluded
1562
+ * (issue #2270 scopes this to method/type documentation). Language-neutral:
1563
+ * a label a given grammar never emits simply never matches.
1564
+ *
1565
+ * Bounded to labels that are also in `embeddings/types.ts` `EMBEDDABLE_LABELS`:
1566
+ * the description is only useful once it reaches the embedding metadata header,
1567
+ * and the embedding pipeline only queries embeddable labels. Extracting docs
1568
+ * for a non-embeddable label is a wasted write that never becomes searchable.
1569
+ * A subset invariant in the unit tests guards against drift. Making currently-
1570
+ * non-embeddable doc-bearing labels (Module, Delegate, Annotation, and C++
1571
+ * `Template`) searchable is tracked as a follow-up — it needs an embedding-
1572
+ * pipeline/schema change beyond this fix. */
1573
+ exports.DOC_BEARING_LABELS = new Set([
1574
+ 'Function',
1575
+ 'Method',
1576
+ 'Constructor',
1577
+ 'Class',
1578
+ 'Interface',
1579
+ 'Enum',
1580
+ 'Struct',
1581
+ 'Trait',
1582
+ 'Record',
1583
+ 'Union',
1584
+ 'Namespace',
1585
+ 'TypeAlias',
1586
+ 'Macro',
1587
+ ]);
1588
+ /**
1589
+ * Build a `LanguageProvider.descriptionExtractor` that surfaces a definition's
1590
+ * leading doc comment as its `description` (issue #2270). For labels in
1591
+ * {@link DOC_BEARING_LABELS} (which is bounded to embeddable labels) the text
1592
+ * then reaches the embedding metadata header and becomes semantically searchable.
1593
+ *
1594
+ * Language-neutral factory (names no language): guards on
1595
+ * {@link DOC_BEARING_LABELS}; callers pass per-language doc-comment behavior via
1596
+ * {@link LeadingDocCommentOptions} (line prefixes, export-style wrappers, …)
1597
+ * which is threaded straight through to {@link extractLeadingDocComment}.
1598
+ */
1599
+ const createLeadingDocDescriptionExtractor = (opts = {}) => {
1600
+ return (nodeLabel, _nodeName, captureMap) => {
1601
+ if (!exports.DOC_BEARING_LABELS.has(nodeLabel))
1602
+ return undefined;
1603
+ const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
1604
+ return definitionNode ? extractLeadingDocComment(definitionNode, opts) : undefined;
1605
+ };
1606
+ };
1607
+ exports.createLeadingDocDescriptionExtractor = createLeadingDocDescriptionExtractor;
1608
+ // ============================================================================
1609
+ // Capture + range helpers (formerly python/ast-utils.ts — language-agnostic)
1610
+ // ============================================================================
1611
+ /** Convert a tree-sitter node to a `Capture` with 1-based line numbers
1612
+ * (matching RFC §2.1). The tag includes the leading `@`. */
1613
+ function nodeToCapture(name, node) {
1614
+ return {
1615
+ name,
1616
+ range: {
1617
+ startLine: node.startPosition.row + 1,
1618
+ startCol: node.startPosition.column,
1619
+ endLine: node.endPosition.row + 1,
1620
+ endCol: node.endPosition.column,
1621
+ },
1622
+ text: node.text,
1623
+ };
1624
+ }
1625
+ /** Build a `Capture` whose range mirrors `atNode` but whose `text` is
1626
+ * caller-supplied. Used to synthesize markers that don't have a
1627
+ * corresponding source token. */
1628
+ function syntheticCapture(name, atNode, text) {
1629
+ return {
1630
+ name,
1631
+ range: {
1632
+ startLine: atNode.startPosition.row + 1,
1633
+ startCol: atNode.startPosition.column,
1634
+ endLine: atNode.endPosition.row + 1,
1635
+ endCol: atNode.endPosition.column,
1636
+ },
1637
+ text,
1638
+ };
1639
+ }
1640
+ function rangeMatches(node, range) {
1641
+ return (node.startPosition.row + 1 === range.startLine &&
1642
+ node.startPosition.column === range.startCol &&
1643
+ node.endPosition.row + 1 === range.endLine &&
1644
+ node.endPosition.column === range.endCol);
1645
+ }
1646
+ /** Walk a subtree to find a node whose range exactly matches AND whose
1647
+ * type matches `expectedType` (when given). When multiple nodes share
1648
+ * the range — e.g., `function_definition` and its inner `block` body
1649
+ * for a one-liner — the type filter disambiguates.
1650
+ *
1651
+ * Iterative depth-first-left-to-right via an explicit stack. Children
1652
+ * are pushed in reverse index order so LIFO pop visits them in source
1653
+ * order. Prunes branches that can't contain the target range by
1654
+ * row bounds — same optimization the prior recursive form used, minus
1655
+ * the early-break since stack-push is cheap. */
1656
+ function findNodeAtRange(root, range, expectedType) {
1657
+ const startRow = range.startLine - 1;
1658
+ const endRow = range.endLine - 1;
1659
+ const stack = [root];
1660
+ while (stack.length > 0) {
1661
+ const node = stack.pop();
1662
+ if (rangeMatches(node, range) && (expectedType === undefined || node.type === expectedType)) {
1663
+ return node;
1664
+ }
1665
+ for (let i = node.namedChildCount - 1; i >= 0; i--) {
1666
+ const child = node.namedChild(i);
1667
+ if (child === null)
1668
+ continue;
1669
+ if (child.endPosition.row < startRow)
1670
+ continue;
1671
+ if (child.startPosition.row > endRow)
1672
+ continue;
1673
+ stack.push(child);
1674
+ }
1675
+ }
1676
+ return null;
1677
+ }
1678
+ /**
1679
+ * Return the captured node if its type is one of `types`, else null.
1680
+ *
1681
+ * The threaded-node equivalent of `findNodeAtRange(root, capture.range, type)`
1682
+ * for the common case where a tree-sitter query already hands you the matched
1683
+ * node (`c.node`): the captured node IS the node at that range, so a type check
1684
+ * is exact and there is no need to re-walk from the tree root (the
1685
+ * O(matches × rootChildren) hot path #1848 hit). Unlike `findNodeAtRange`, this
1686
+ * does NOT traverse — the caller must already hold the node; for a multi-type
1687
+ * call the node must literally be one of `types` (no fallback search).
1688
+ *
1689
+ * Used by every language's scope-capture path (go/python/ruby/php/rust/csharp).
1690
+ */
1691
+ function nodeIfType(node, ...types) {
1692
+ return node !== undefined && types.includes(node.type) ? node : null;
1693
+ }