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,1835 @@
1
+ "use strict";
2
+ /**
3
+ * Scope-chain lookup primitives shared across language providers.
4
+ *
5
+ * Five functions:
6
+ * - `findReceiverTypeBinding` — walk scope.typeBindings up the chain
7
+ * for a receiver name.
8
+ * - `lookupBindingsAt` — read finalized + augmented binding refs at
9
+ * one scope, deduped by `def.nodeId`. The dual-source-aware
10
+ * primitive every other binding lookup composes with.
11
+ * - `findClassBindingInScope` — walk scope.bindings + the indexes via
12
+ * `lookupBindingsAt` for a class-kind binding.
13
+ * - `findOwnedMember` — find a method/field owned by a class def
14
+ * across all parsed files by (ownerId, simpleName).
15
+ * - `findExportedDef` — find a file-level exported def (top-of-module
16
+ * class / function) by simpleName.
17
+ *
18
+ * Next-consumer contract: every OO or module-capable language hits the
19
+ * same pre-finalize / post-finalize binding split and the same
20
+ * "resolve member on owner with MRO" pattern. All four are reusable
21
+ * as-is for TypeScript, Java, Kotlin, Ruby, etc.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.lookupBindingsAt = lookupBindingsAt;
25
+ exports.namesAtScope = namesAtScope;
26
+ exports.isClassLike = isClassLike;
27
+ exports.isReceiverOwnedButUnbound = isReceiverOwnedButUnbound;
28
+ exports.isNamespaceNameShadowed = isNamespaceNameShadowed;
29
+ exports.findReceiverTypeBinding = findReceiverTypeBinding;
30
+ exports.namespaceTypeBindingFor = namespaceTypeBindingFor;
31
+ exports.moduleScopeIdOf = moduleScopeIdOf;
32
+ exports.findAllClassBindingsInScope = findAllClassBindingsInScope;
33
+ exports.findClassBindingInScope = findClassBindingInScope;
34
+ exports.resolveClassBindingForName = resolveClassBindingForName;
35
+ exports.resolveInheritanceBaseInScope = resolveInheritanceBaseInScope;
36
+ exports.resolveAmbiguousInheritanceBaseViaImports = resolveAmbiguousInheritanceBaseViaImports;
37
+ exports.isOwnableValueLabel = isOwnableValueLabel;
38
+ exports.findValueBindingInScope = findValueBindingInScope;
39
+ exports.findCallableBindingInScope = findCallableBindingInScope;
40
+ exports.findAllCallableBindingCandidatesInScope = findAllCallableBindingCandidatesInScope;
41
+ exports.findAllCallableBindingsInScope = findAllCallableBindingsInScope;
42
+ exports.findCallableBindingsAndAdlBlocker = findCallableBindingsAndAdlBlocker;
43
+ exports.populateClassOwnedMembers = populateClassOwnedMembers;
44
+ exports.tagNamespacePrefixes = tagNamespacePrefixes;
45
+ exports.findEnclosingClassDef = findEnclosingClassDef;
46
+ exports.findExportedDefByName = findExportedDefByName;
47
+ exports.findOwnedMember = findOwnedMember;
48
+ exports.findExportedDef = findExportedDef;
49
+ const qualified_name_js_1 = require("../../utils/qualified-name.js");
50
+ const template_arguments_js_1 = require("../../utils/template-arguments.js");
51
+ const EMPTY_BINDINGS = Object.freeze([]);
52
+ /**
53
+ * Look up binding refs at `scopeId` for `name`, consulting both the
54
+ * finalize-owned `bindings` channel and the post-finalize
55
+ * `bindingAugmentations` channel (see invariant I8 in
56
+ * `contract/scope-resolver.ts`). Finalized refs come first; augmented
57
+ * refs append, deduped by `def.nodeId` so a sibling that's also
58
+ * explicitly imported doesn't double-emit.
59
+ *
60
+ * Returns a shared frozen empty array when neither channel has the
61
+ * name — callers can compare against `=== EMPTY_BINDINGS` if they
62
+ * want a fast-path miss check. The bucket arrays are returned by
63
+ * reference when only one channel populates them; the merged path
64
+ * allocates a fresh array.
65
+ *
66
+ * Walker primitives (`findClassBindingInScope`,
67
+ * `findCallableBindingInScope`, `findExportedDefByName`) and
68
+ * post-finalize passes that read finalized bindings (e.g.
69
+ * `propagateImportedReturnTypes`, `namespace-targets`) MUST go
70
+ * through this helper instead of `scopes.bindings.get(...)` directly,
71
+ * so the augmentation channel is always visible.
72
+ */
73
+ function lookupBindingsAt(scopeId, name, scopes) {
74
+ const finalized = scopes.bindings.get(scopeId)?.get(name);
75
+ const augmented = scopes.bindingAugmentations.get(scopeId)?.get(name);
76
+ const workspace = scopes.workspaceFqnBindings?.get(name);
77
+ // Per-namespace channel (#1871 named-namespace generalization). Gated by
78
+ // accessibility: only a *module* scope carries an `accessibleNamespacesByScope`
79
+ // entry, so this collects nothing at child scopes and at module scopes only for
80
+ // the namespaces that file can see. Empty (no entry) for every non-C# bundle,
81
+ // so the behavior of the three pre-existing channels is unchanged.
82
+ const namespaceRefs = collectNamespaceFqnBindings(scopeId, name, scopes);
83
+ const fLen = finalized?.length ?? 0;
84
+ const aLen = augmented?.length ?? 0;
85
+ const wLen = workspace?.length ?? 0;
86
+ const nLen = namespaceRefs?.length ?? 0;
87
+ if (fLen === 0 && aLen === 0 && wLen === 0 && nLen === 0)
88
+ return EMPTY_BINDINGS;
89
+ if (aLen === 0 && wLen === 0 && nLen === 0)
90
+ return finalized;
91
+ if (fLen === 0 && wLen === 0 && nLen === 0)
92
+ return augmented;
93
+ if (fLen === 0 && aLen === 0 && nLen === 0)
94
+ return workspace;
95
+ if (fLen === 0 && aLen === 0 && wLen === 0)
96
+ return namespaceRefs;
97
+ // Merge in precedence order, deduped by `def.nodeId` so the strongest source
98
+ // wins duplicate metadata. Named-namespace refs come BEFORE the flat global
99
+ // `workspace` channel: pre-#1871 these lived in `bindingAugmentations` (which
100
+ // `lookupBindingsAt` already ranks above `workspaceFqnBindings`), so a name in
101
+ // both an accessible named namespace and the global namespace must still
102
+ // resolve named-first. Order: finalized > augmented > namespace > workspace.
103
+ const seen = new Set();
104
+ const out = [];
105
+ for (const src of [finalized, augmented, namespaceRefs, workspace]) {
106
+ if (src === undefined)
107
+ continue;
108
+ for (const r of src) {
109
+ if (seen.has(r.def.nodeId))
110
+ continue;
111
+ seen.add(r.def.nodeId);
112
+ out.push(r);
113
+ }
114
+ }
115
+ return out;
116
+ }
117
+ /**
118
+ * Collect `BindingRef`s for `name` from the per-namespace channel
119
+ * (`namespaceFqnBindings`) across every namespace accessible from `scopeId`.
120
+ * Accessibility comes from `accessibleNamespacesByScope`, which is keyed by
121
+ * *module* scope id — so this returns `undefined` at non-module scopes and at
122
+ * every scope in a bundle that didn't populate the channel (all non-C# today).
123
+ * Language-neutral: keyed only by namespace strings and the index.
124
+ */
125
+ function collectNamespaceFqnBindings(scopeId, name, scopes) {
126
+ const namespaces = scopes.accessibleNamespacesByScope?.get(scopeId);
127
+ if (namespaces === undefined || namespaces.length === 0)
128
+ return undefined;
129
+ let collected;
130
+ for (const ns of namespaces) {
131
+ const bucket = scopes.namespaceFqnBindings?.get(ns)?.get(name);
132
+ if (bucket !== undefined && bucket.length > 0) {
133
+ if (collected === undefined)
134
+ collected = [];
135
+ for (const r of bucket)
136
+ collected.push(r);
137
+ }
138
+ }
139
+ return collected;
140
+ }
141
+ const EMPTY_NAMES = Object.freeze([]);
142
+ /**
143
+ * Return the union of bound names at `scopeId` across both the
144
+ * finalized and augmented channels. Companion to `lookupBindingsAt`
145
+ * for callers that need to iterate every name at a scope (e.g.
146
+ * `propagateImportedReturnTypes`). Order is not guaranteed; callers
147
+ * that need stable iteration should sort externally.
148
+ *
149
+ * Fast paths (zero allocation) when at most one channel is populated:
150
+ * returns the underlying `Map.keys()` iterator directly. Only when both
151
+ * channels carry names do we materialize a `Set` for deduplication.
152
+ *
153
+ * Scope: enumerates only the per-scope `bindings` and `bindingAugmentations`
154
+ * channels. It deliberately EXCLUDES the scope-independent
155
+ * `workspaceFqnBindings` channel (PHP FQN keys, C# global-namespace simple
156
+ * names). `lookupBindingsAt` consults that third channel when resolving a
157
+ * specific name, but name *enumeration* here does not — those names apply at
158
+ * every scope and would flood per-scope callers. Callers that need
159
+ * workspace-level names must read `workspaceFqnBindings` directly.
160
+ */
161
+ function namesAtScope(scopeId, scopes) {
162
+ const finalized = scopes.bindings.get(scopeId);
163
+ const augmented = scopes.bindingAugmentations.get(scopeId);
164
+ const fSize = finalized?.size ?? 0;
165
+ const aSize = augmented?.size ?? 0;
166
+ if (fSize === 0 && aSize === 0)
167
+ return EMPTY_NAMES;
168
+ if (aSize === 0)
169
+ return finalized.keys();
170
+ if (fSize === 0)
171
+ return augmented.keys();
172
+ const out = new Set(finalized.keys());
173
+ for (const name of augmented.keys())
174
+ out.add(name);
175
+ return out;
176
+ }
177
+ /**
178
+ * True when a def's `type` names a class-like declaration — every kind
179
+ * that collapses to `@scope.class` in the scope-extractor query contract.
180
+ *
181
+ * Semantics widened historically from `'Class' | 'Interface'` to cover
182
+ * C#-shape languages (struct, record, enum, trait). Languages that emit
183
+ * only `'Class'` are unaffected — the extra kinds never appear in their
184
+ * parsed output.
185
+ */
186
+ function isClassLike(t) {
187
+ return (t === 'Class' ||
188
+ t === 'Interface' ||
189
+ t === 'Struct' ||
190
+ t === 'Record' ||
191
+ t === 'Enum' ||
192
+ t === 'Trait');
193
+ }
194
+ /**
195
+ * Walk the scope chain from `startScope` looking for a typeBinding
196
+ * named `receiverName`. Returns the TypeRef or undefined if no binding
197
+ * exists in the chain.
198
+ *
199
+ * A scope that declares `ownsReceivers.has(receiverName)` terminates the
200
+ * walk with `undefined` (#2701): it binds that receiver itself, so an
201
+ * enclosing scope's binding is not visible through it. The check runs
202
+ * AFTER this scope's own `typeBindings`, so a scope that both owns and
203
+ * binds the receiver — a class method, which is where `this` is bound TO
204
+ * the class — still resolves normally. The namespace/global fallbacks
205
+ * below are also skipped: they answer "which type is named X", which is a
206
+ * different question from "what is this scope's receiver", and reaching
207
+ * them for an owned-but-unbound receiver is how a static method or a
208
+ * detached callback acquires a fabricated one.
209
+ */
210
+ /**
211
+ * True when `receiverName` is DEFINITIVELY unresolvable at `startScope`:
212
+ * a scope on the chain declares it owns that receiver (`Scope.ownsReceivers`)
213
+ * and carries no type binding for it (#2701).
214
+ *
215
+ * This is a stronger statement than `findReceiverTypeBinding` returning
216
+ * `undefined`, which only means "no type found" — an ordinary miss that later
217
+ * passes are free to resolve by other means. Here the language has said the
218
+ * receiver is REBOUND at this scope, so no enclosing type can be its type:
219
+ * `this.m()` inside a nested JS/TS `function` is a call on whatever the
220
+ * function is invoked with, which the graph does not model. A member call
221
+ * whose receiver is unresolvable in this sense must be suppressed rather
222
+ * than left to the receiver-blind lexical fallback in `lookupCore`, which
223
+ * would find the enclosing class's member by name alone.
224
+ *
225
+ * Returns false for every language that leaves `ownsReceivers` unset.
226
+ */
227
+ function isReceiverOwnedButUnbound(startScope, receiverName, scopes) {
228
+ let currentId = startScope;
229
+ const visited = new Set();
230
+ while (currentId !== null) {
231
+ if (visited.has(currentId))
232
+ return false;
233
+ visited.add(currentId);
234
+ const scope = scopes.scopeTree.getScope(currentId);
235
+ if (scope === undefined)
236
+ return false;
237
+ if (scope.typeBindings.has(receiverName))
238
+ return false;
239
+ if (scope.ownsReceivers?.has(receiverName) === true)
240
+ return true;
241
+ currentId = scope.parent;
242
+ }
243
+ return false;
244
+ }
245
+ /**
246
+ * True when a declaration between the call site and its module scope shadows a
247
+ * file-level namespace import of the same name. Namespace targets are collected
248
+ * per FILE, so every consumer of that map must apply this lexical guard before
249
+ * trusting it at an inner scope — otherwise `def f(pkg): pkg.db.query()`
250
+ * resolves through the import that the parameter shadows, producing a wrong
251
+ * edge rather than a missing one.
252
+ *
253
+ * A namespace key may itself be a dotted import path (`pkg.db`, #2826), but the
254
+ * name a declaration can shadow is always the ROOT identifier — `pkg = Decoy()`
255
+ * shadows `pkg.db` too. Testing the whole dotted string would never match a
256
+ * binding, so the guard would silently stop guarding for exactly the keys it
257
+ * was extended to cover. Single-segment names are unaffected: their root is
258
+ * themselves.
259
+ *
260
+ * Fails closed (returns `true`) on a missing scope or a parent cycle: for every
261
+ * caller, suppressing a resolution costs a missing edge, while trusting a
262
+ * corrupt scope chain costs a wrong one.
263
+ *
264
+ * Reads `scope.bindings` DIRECTLY rather than through `lookupBindingsAt`, and
265
+ * that is deliberate — the opposite of the fix #2745 applied to Rust's
266
+ * `headBoundLocally`. There the question was "is this name bound at all?", so
267
+ * missing the finalized/augmented import channels lost real bindings. Here the
268
+ * question is "does something LOCAL shadow the import?", and the import's own
269
+ * finalized binding is the one thing that must NOT count: routing this through
270
+ * `lookupBindingsAt` would find the namespace import shadowing itself and
271
+ * suppress every namespace receiver in the workspace. Locals, parameters and
272
+ * lexical names all live in the scope's own tables, which is exactly the set
273
+ * this walk wants.
274
+ */
275
+ function isNamespaceNameShadowed(namespaceName, inScope, scopes) {
276
+ const firstDot = namespaceName.indexOf('.');
277
+ const rootName = firstDot === -1 ? namespaceName : namespaceName.slice(0, firstDot);
278
+ let currentId = inScope;
279
+ const visited = new Set();
280
+ while (currentId !== null) {
281
+ if (visited.has(currentId))
282
+ return true;
283
+ visited.add(currentId);
284
+ const scope = scopes.scopeTree.getScope(currentId);
285
+ if (scope === undefined)
286
+ return true;
287
+ // Stop AT the module scope without inspecting it. In languages where a
288
+ // namespace import IS a variable declaration — CommonJS
289
+ // `const svc = require('./svc')` — the import puts its own name into the
290
+ // module scope's tables, so inspecting them reads the import as its own
291
+ // shadow and suppresses every receiver it was meant to enable (#2723).
292
+ // The contract is "a declaration BETWEEN the call site and its module
293
+ // scope", and the module scope is the floor, not a rung.
294
+ if (scope.kind === 'Module')
295
+ return false;
296
+ if (scope.kind !== 'Object' &&
297
+ (scope.bindings.has(rootName) ||
298
+ scope.typeBindings.has(rootName) ||
299
+ scope.lexicalNames?.has(rootName) === true ||
300
+ scope.ownedDefs.some((def) => {
301
+ const qualifiedName = def.qualifiedName;
302
+ if (qualifiedName === undefined)
303
+ return false;
304
+ const dot = qualifiedName.lastIndexOf('.');
305
+ return (dot === -1 ? qualifiedName : qualifiedName.slice(dot + 1)) === rootName;
306
+ }))) {
307
+ return true;
308
+ }
309
+ currentId = scope.parent;
310
+ }
311
+ return true;
312
+ }
313
+ function findReceiverTypeBinding(startScope, receiverName, scopes) {
314
+ let currentId = startScope;
315
+ const visited = new Set();
316
+ let moduleScopeId = null;
317
+ while (currentId !== null) {
318
+ if (visited.has(currentId))
319
+ return undefined;
320
+ visited.add(currentId);
321
+ const scope = scopes.scopeTree.getScope(currentId);
322
+ if (scope === undefined)
323
+ return undefined;
324
+ const typeRef = scope.typeBindings.get(receiverName);
325
+ if (typeRef !== undefined)
326
+ return typeRef;
327
+ if (scope.ownsReceivers?.has(receiverName) === true)
328
+ return undefined;
329
+ if (scope.kind === 'Module')
330
+ moduleScopeId = currentId;
331
+ currentId = scope.parent;
332
+ }
333
+ // Fallback 1 — named namespaces accessible from this file (own + `using`d),
334
+ // gated by `accessibleNamespacesByScope`. Consulted BEFORE the global channel
335
+ // so a more-specific named binding wins, matching the pre-#1871 order where
336
+ // these lived in the file's own `Scope.typeBindings` (the chain, above the
337
+ // global fallback). Shared-channel routing avoids the O(files × names) blow-up.
338
+ const named = namespaceTypeBindingFor(moduleScopeId, receiverName, scopes);
339
+ if (named !== undefined)
340
+ return named;
341
+ // Fallback 2 — global/default namespace: C# global types are visible from
342
+ // every file (see `workspaceTypeBindings` doc), so this flat channel is the
343
+ // final, unconditional fallback (#1871).
344
+ return scopes.workspaceTypeBindings?.get(receiverName);
345
+ }
346
+ /**
347
+ * Resolve a typeBinding for `name` from the per-namespace channel
348
+ * (`namespaceTypeBindings`) across the namespaces accessible from `moduleScopeId`.
349
+ * First accessible-namespace hit wins. Returns `undefined` when the module has no
350
+ * accessibility entry (non-module scope id, or a bundle that didn't populate the
351
+ * channel — all non-C# today). Shared by the two typeBindings chain-walkers so
352
+ * the named-namespace fallback stays identical between them.
353
+ */
354
+ function namespaceTypeBindingFor(moduleScopeId, name, scopes) {
355
+ if (moduleScopeId === null)
356
+ return undefined;
357
+ const namespaces = scopes.accessibleNamespacesByScope?.get(moduleScopeId);
358
+ if (namespaces === undefined)
359
+ return undefined;
360
+ for (const ns of namespaces) {
361
+ const hit = scopes.namespaceTypeBindings?.get(ns)?.get(name);
362
+ if (hit !== undefined)
363
+ return hit;
364
+ }
365
+ return undefined;
366
+ }
367
+ /**
368
+ * Walk the scope chain from `startScope` to its enclosing Module scope id, or
369
+ * `null` if none is found. Used by chain-followers that need the module scope to
370
+ * consult the accessibility-gated per-namespace channels.
371
+ */
372
+ function moduleScopeIdOf(startScope, scopes) {
373
+ let currentId = startScope;
374
+ const visited = new Set();
375
+ while (currentId !== null) {
376
+ if (visited.has(currentId))
377
+ return null;
378
+ visited.add(currentId);
379
+ const scope = scopes.scopeTree.getScope(currentId);
380
+ if (scope === undefined)
381
+ return null;
382
+ if (scope.kind === 'Module')
383
+ return currentId;
384
+ currentId = scope.parent;
385
+ }
386
+ return null;
387
+ }
388
+ /**
389
+ * Look up a class-like binding by name in the given scope's chain.
390
+ *
391
+ * "Class-like" covers `Class | Interface | Struct | Record | Enum |
392
+ * Trait` via the shared `isClassLike` predicate — every kind that
393
+ * collapses to `@scope.class` in the scope-extractor query contract.
394
+ *
395
+ * Walks the scope chain upward and consults TWO sources at each step:
396
+ * 1. `scope.bindings` — populated during scope-extraction Pass 2 with
397
+ * local declarations (`origin: 'local'`).
398
+ * 2. The cross-file finalized + augmented bindings, via
399
+ * `lookupBindingsAt` (per I8: finalized = canonical immutable
400
+ * output; augmented = post-finalize hooks like
401
+ * `populateNamespaceSiblings`).
402
+ *
403
+ * Without (2) we'd miss every cross-file class-receiver call.
404
+ */
405
+ /**
406
+ * Every class-like definition visible for `name`, from the scope chain AND the
407
+ * qualified-name index, deduped by `nodeId`.
408
+ *
409
+ * Exists because `walkScopeChain` returns the FIRST match and cannot report a
410
+ * collision, so a caller that widens what a name can match (the decoration
411
+ * normalizer below) has no way to tell "one answer" from "picked the nearest of
412
+ * several". Mirrors `findAllCallableBindingsInScope`, which solved the same
413
+ * problem for callables.
414
+ */
415
+ function findAllClassBindingsInScope(startScope, name, scopes) {
416
+ return classBindingsVisibleFrom(lexicalClassBindingsInScope(startScope, name, scopes), name, scopes);
417
+ }
418
+ /**
419
+ * {@link findAllClassBindingsInScope} for a caller that already holds the
420
+ * scope-chain half (see {@link lexicalClassBindingsInScope}), so the chain is
421
+ * walked once rather than once per question asked about the same name.
422
+ *
423
+ * The chain wins outright when it binds the name: an inner binding shadows
424
+ * anything the qualified-name index would contribute.
425
+ */
426
+ function classBindingsVisibleFrom(lexical, name, scopes) {
427
+ if (lexical.length > 0)
428
+ return lexical;
429
+ const byNodeId = new Map();
430
+ for (const def of classDefsByQualifiedName(name, scopes))
431
+ byNodeId.set(def.nodeId, def);
432
+ return [...byNodeId.values()];
433
+ }
434
+ /** Bounded so a pathological stripper cannot spin. Real decoration nests
435
+ * shallowly (`*[]T`, `const T&`); three layers is generous. */
436
+ const MAX_DECORATION_LAYERS = 3;
437
+ /** Memo for {@link typeParameterNamesInScope}, keyed by index bundle then
438
+ * scope. One bundle per model, so the outer WeakMap releases with it. */
439
+ const typeParameterNamesByBundle = new WeakMap();
440
+ const NO_TYPE_PARAMETERS = Object.freeze(new Set());
441
+ /**
442
+ * Every name the scope chain above `scopeId` (inclusive) binds as a declared
443
+ * TYPE PARAMETER.
444
+ *
445
+ * Memoized per scope, and each scope's answer is built from its PARENT's, so a
446
+ * chain is walked once and every scope on it is O(own defs) rather than
447
+ * O(depth × defs). That matters because the caller runs on every class-binding
448
+ * lookup, and a module scope's `ownedDefs` is the whole file.
449
+ */
450
+ function typeParameterNamesInScope(scopeId, scopes) {
451
+ let byScope = typeParameterNamesByBundle.get(scopes);
452
+ if (byScope === undefined) {
453
+ byScope = new Map();
454
+ typeParameterNamesByBundle.set(scopes, byScope);
455
+ }
456
+ const memo = byScope.get(scopeId);
457
+ if (memo !== undefined)
458
+ return memo;
459
+ // Collect the chain first, then fold from the top down, so the recursion is
460
+ // an explicit loop (a deep scope chain must not risk the call stack) and
461
+ // every scope passed through is memoized on the way back.
462
+ const chain = [];
463
+ const seen = new Set();
464
+ let cursor = scopeId;
465
+ let inherited = NO_TYPE_PARAMETERS;
466
+ while (cursor !== null && !seen.has(cursor)) {
467
+ seen.add(cursor);
468
+ const cached = byScope.get(cursor);
469
+ if (cached !== undefined) {
470
+ inherited = cached;
471
+ break;
472
+ }
473
+ chain.push(cursor);
474
+ cursor = scopes.scopeTree.getScope(cursor)?.parent ?? null;
475
+ }
476
+ for (let i = chain.length - 1; i >= 0; i -= 1) {
477
+ const id = chain[i];
478
+ const scope = scopes.scopeTree.getScope(id);
479
+ let own;
480
+ for (const def of scope?.ownedDefs ?? []) {
481
+ for (const parameter of def.typeParameters ?? []) {
482
+ if (parameter.name.length === 0)
483
+ continue;
484
+ own ??= new Set(inherited);
485
+ own.add(parameter.name);
486
+ }
487
+ }
488
+ inherited = own ?? inherited;
489
+ byScope.set(id, inherited);
490
+ }
491
+ return inherited;
492
+ }
493
+ /**
494
+ * Does the scope chain at `scopeId` bind `name` as a declared TYPE PARAMETER?
495
+ *
496
+ * The question a class-binding lookup has to ask before it answers, because a
497
+ * type parameter and a class are spelled identically and only the declaration
498
+ * says which one a name is. `class Box<T> { t: T }` beside a workspace
499
+ * `export class T` resolved `t` to the CLASS and emitted a confident wrong edge
500
+ * from every member call on `t` — the exact failure mode this subsystem treats
501
+ * as worse than a missing edge.
502
+ *
503
+ * WHY LEXICAL GROUNDING CANNOT SUBSTITUTE. The erasure grounds in
504
+ * `resolveErasedBaseName` all ask "can the file SEE a declaration by this
505
+ * name", and here it plainly can: `export class T` is imported, bound, and
506
+ * lexically visible. Visibility is not the defect — the name means something
507
+ * else at this site regardless of what else is visible, and only the enclosing
508
+ * declaration's parameter list records that. Measured: with the grounding rule
509
+ * in place the false edge still emitted.
510
+ *
511
+ * ABSENCE IS NOT EVIDENCE. `typeParameters` is populated only by the languages
512
+ * whose captures were extended for it, and is absent both for a non-generic
513
+ * declaration and for every declaration in a language that does not populate it
514
+ * yet. So only a POSITIVE match declines; an absent list changes nothing, which
515
+ * is what keeps every unconverted language behaving exactly as it does today.
516
+ */
517
+ function bindsTypeParameter(scopeId, name, scopes) {
518
+ if (name.length === 0)
519
+ return false;
520
+ return typeParameterNamesInScope(scopeId, scopes).has(name);
521
+ }
522
+ /**
523
+ * The declared parameter `name` refers to at `scopeId`, nearest declaration
524
+ * first, or `undefined` when `name` is not a type parameter here.
525
+ *
526
+ * Separate from {@link bindsTypeParameter} because the guard only needs to know
527
+ * THAT a name is a parameter, while resolving through a bound needs the
528
+ * parameter itself — and the memoized name set deliberately keeps no payload so
529
+ * that the guard, which runs on every lookup, stays a single hash probe.
530
+ */
531
+ function typeParameterAt(scopeId, name, scopes) {
532
+ let cursor = scopeId;
533
+ const seen = new Set();
534
+ while (cursor !== null && !seen.has(cursor)) {
535
+ seen.add(cursor);
536
+ const scope = scopes.scopeTree.getScope(cursor);
537
+ for (const def of scope?.ownedDefs ?? []) {
538
+ const hit = def.typeParameters?.find((parameter) => parameter.name === name);
539
+ if (hit !== undefined)
540
+ return hit;
541
+ }
542
+ cursor = scope?.parent ?? null;
543
+ }
544
+ return undefined;
545
+ }
546
+ /**
547
+ * The single class-like name a declared bound names, or `undefined` when the
548
+ * bound names none or names more than one.
549
+ *
550
+ * DECLINING ON AN INTERSECTION is the point. `T extends Repo & Closeable` and
551
+ * `T: Repo + Clone` make a member reachable through EITHER bound, so picking one
552
+ * — the first, as erasure would — mints a confidently-attributed edge to a
553
+ * declaration that may not own the member at all. Two candidates and no way to
554
+ * choose is exactly the case this file already answers with `undefined` in
555
+ * `findClassBindingInScope`'s decoration fallback: a missing edge is
556
+ * recoverable, a wrong one is not.
557
+ *
558
+ * Type ARGUMENTS on the bound are erased (`T extends Repo<User>` → `Repo`),
559
+ * which is sound here for the same reason the erased base-name route exists: the
560
+ * members are declared once, on the declaration written against its parameters.
561
+ */
562
+ function soleBoundBaseName(bound) {
563
+ // `&` (Java, TypeScript) and `+` (Rust, Kotlin) both compose bounds. Split on
564
+ // whichever appears OUTSIDE brackets, so `Repo<A & B>` stays one bound.
565
+ let depth = 0;
566
+ for (let i = 0; i < bound.length; i += 1) {
567
+ const ch = bound[i];
568
+ if (ch === '<' || ch === '(' || ch === '[' || ch === '{')
569
+ depth += 1;
570
+ else if (ch === '>' || ch === ')' || ch === ']' || ch === '}')
571
+ depth -= 1;
572
+ else if (depth === 0 && (ch === '&' || ch === '+'))
573
+ return undefined;
574
+ }
575
+ const base = (0, template_arguments_js_1.stripTemplateArguments)(bound).trim();
576
+ return base.length === 0 ? undefined : base;
577
+ }
578
+ function findClassBindingInScope(startScope, receiverName, scopes,
579
+ /**
580
+ * OPT-IN. When supplied, a name that binds nothing is retried with decoration
581
+ * stripped one layer at a time, and each retry must resolve to exactly ONE
582
+ * class-like definition or it declines.
583
+ *
584
+ * Opt-in rather than global because roughly two dozen call sites use the shape
585
+ * `findClassBindingInScope(...) ?? otherResolver(...)`: turning a former
586
+ * `undefined` into a hit SUPPRESSES the fallback that used to answer, which
587
+ * would retarget inheritance edges and bypass generic-specialization
588
+ * selection. Only receiver-chain base and step resolution passes this.
589
+ */
590
+ stripDecoration) {
591
+ // A TYPE PARAMETER is not a class, and it is checked before every route below
592
+ // rather than inside one of them because each route would otherwise reach a
593
+ // same-named class by its own channel: the scope chain when the class is
594
+ // imported, the qualified-name index when it is not, and the decoration
595
+ // fallback after stripping. The declaration that introduced the parameter is
596
+ // the only thing that knows, and it knows for all three.
597
+ if (bindsTypeParameter(startScope, receiverName, scopes)) {
598
+ return resolveThroughTypeParameterBound(startScope, receiverName, scopes, stripDecoration);
599
+ }
600
+ const local = walkScopeChain(startScope, receiverName, scopes, (def) => isClassLike(def.type));
601
+ if (local !== undefined)
602
+ return local;
603
+ // Fallback for languages (Go) where namespace-style imports don't
604
+ // create scope bindings: resolve via QualifiedNameIndex. Only fires
605
+ // when the scope-chain walk found nothing; single-match wins.
606
+ const qnames = scopes.qualifiedNames.get(receiverName);
607
+ if (qnames.length === 1) {
608
+ const def = scopes.defs.get(qnames[0]);
609
+ if (def !== undefined && isClassLike(def.type))
610
+ return def;
611
+ }
612
+ // Second fallback: dotted names like "models.User" — try the simple
613
+ // name (tail after last dot) for languages where defs are indexed by
614
+ // simple name (Go). Only when the dotted lookup fails.
615
+ if (receiverName.includes('.')) {
616
+ const simple = receiverName.slice(receiverName.lastIndexOf('.') + 1);
617
+ if (simple.length > 0 && simple !== receiverName) {
618
+ const simpleIds = scopes.qualifiedNames.get(simple);
619
+ if (simpleIds.length === 1) {
620
+ const def = scopes.defs.get(simpleIds[0]);
621
+ if (def !== undefined && isClassLike(def.type))
622
+ return def;
623
+ }
624
+ }
625
+ }
626
+ // Decoration fallback (opt-in). Every branch above works on the name exactly
627
+ // as written; only when none of them bound anything do we consider that the
628
+ // name may be a decorated spelling of one that would.
629
+ if (stripDecoration !== undefined) {
630
+ let current = receiverName;
631
+ for (let layer = 0; layer < MAX_DECORATION_LAYERS; layer++) {
632
+ const stripped = stripDecoration(current);
633
+ if (stripped === undefined || stripped === current || stripped.length === 0)
634
+ break;
635
+ current = stripped;
636
+ const candidates = findAllClassBindingsInScope(startScope, current, scopes);
637
+ // Exactly one, or decline. Two same-named classes reachable from here mean
638
+ // the decoration was carrying the only disambiguating information, and
639
+ // picking the nearest would mint a confident wrong edge — the failure this
640
+ // whole line of work exists to avoid. A missing edge is recoverable.
641
+ if (candidates.length === 1)
642
+ return candidates[0];
643
+ if (candidates.length > 1)
644
+ return undefined;
645
+ }
646
+ }
647
+ return undefined;
648
+ }
649
+ /**
650
+ * What a TYPE PARAMETER used in type position resolves to — its declared BOUND
651
+ * when it states exactly one, and nothing when it is unbounded.
652
+ *
653
+ * `class Box<T extends Repo> { t: T; run() { this.t.save(); } }` has one sound
654
+ * answer for `this.t.save()`: the member set a `T` is GUARANTEED to have is its
655
+ * bound's, so `Repo.save` is the target the declaration itself licenses. An
656
+ * unbounded `class Box2<T>` licenses nothing — `T` has no members — and gets
657
+ * `undefined`, which is the whole of the Gap-C fix.
658
+ *
659
+ * ONE HOP ONLY. The retry is guarded against a bound that is itself a parameter
660
+ * (`class Box<T extends U, U extends Repo>`), so the recursion cannot chain or
661
+ * cycle. Following such a chain is sound in principle but has no measured case
662
+ * behind it, and an unbounded step in the middle would have to decline anyway.
663
+ */
664
+ function resolveThroughTypeParameterBound(startScope, parameterName, scopes, stripDecoration) {
665
+ const bound = typeParameterAt(startScope, parameterName, scopes)?.bound;
666
+ if (bound === undefined)
667
+ return undefined;
668
+ const baseName = soleBoundBaseName(bound);
669
+ if (baseName === undefined || baseName === parameterName)
670
+ return undefined;
671
+ // A bound naming another parameter terminates here rather than recursing.
672
+ if (bindsTypeParameter(startScope, baseName, scopes))
673
+ return undefined;
674
+ return findClassBindingInScope(startScope, baseName, scopes, stripDecoration);
675
+ }
676
+ function normalizeTemplateArgToken(value) {
677
+ return value.replace(/\s+/g, '');
678
+ }
679
+ /**
680
+ * A definition that pins its OWN concrete type arguments (`templateArguments`
681
+ * is set) — the shape a scope extractor records for a declaration written
682
+ * against particular arguments rather than against its parameters, e.g. C++
683
+ * `template <> struct Vec<bool>` (`['bool']`) or `template <class T> struct
684
+ * Vec<T*>` (`['T*']`).
685
+ *
686
+ * The distinction that matters to the lookup below: such a definition serves
687
+ * exactly ONE family of instantiations, so the only sound way to select it is
688
+ * the exact-argument match. A declaration written against its parameters —
689
+ * `template <class T> struct Vec`, `class Repo<T>` in TypeScript, C# and every
690
+ * other language measured — carries NOTHING here (the extractor reads arguments
691
+ * off the declared name, and the name is bare), which is precisely why it can
692
+ * never win that match and must be reachable by the base-name route instead.
693
+ */
694
+ function carriesOwnTemplateArguments(def) {
695
+ return def.templateArguments !== undefined && def.templateArguments.length > 0;
696
+ }
697
+ /** Class-like defs registered in the workspace-wide qualified-name index under
698
+ * `name`. Workspace-WIDE: no scope filtering, so a caller must treat this as
699
+ * the weaker source and prefer lexically visible candidates. */
700
+ function classDefsByQualifiedName(name, scopes) {
701
+ const out = [];
702
+ for (const id of scopes.qualifiedNames.get(name)) {
703
+ const def = scopes.defs.get(id);
704
+ if (def !== undefined && isClassLike(def.type))
705
+ out.push(def);
706
+ }
707
+ return out;
708
+ }
709
+ /** Defs from `candidates` whose own template arguments equal `wantedArgs`
710
+ * token-for-token (whitespace already squeezed on both sides). */
711
+ function matchingTemplateArguments(candidates, wantedArgs) {
712
+ return candidates.filter((def) => {
713
+ const defArgs = def.templateArguments?.map(normalizeTemplateArgToken);
714
+ return (defArgs !== undefined &&
715
+ defArgs.length === wantedArgs.length &&
716
+ defArgs.every((value, i) => value === wantedArgs[i]));
717
+ });
718
+ }
719
+ /**
720
+ * Class-like defs the SCOPE CHAIN binds for `name` — locals, imports, wildcards,
721
+ * namespace siblings; everything `findAllBindingsInScope` reaches. No
722
+ * workspace-index fallback, which is the entire point: this is the set that
723
+ * answers "can the file see a declaration by this name", and
724
+ * `findAllClassBindingsInScope` deliberately cannot answer it because it falls
725
+ * through to the scope-free index when the chain is silent.
726
+ */
727
+ function lexicalClassBindingsInScope(startScope, name, scopes) {
728
+ return findAllBindingsInScope(startScope, name, scopes, (def) => isClassLike(def.type));
729
+ }
730
+ /**
731
+ * The one declaration among `candidates` written against its PARAMETERS rather
732
+ * than against particular arguments — or `undefined` when there is not exactly
733
+ * one.
734
+ *
735
+ * ORDER-INDEPENDENT by construction, and that is why it exists separately from
736
+ * "take the first": an unordered candidate set (the workspace index, whose order
737
+ * is insertion order) must never let source order decide a call target. The
738
+ * scope-chain route keeps its nearest-first answer; only the index routes use
739
+ * this.
740
+ */
741
+ function theInstantiationAgnosticDeclaration(candidates) {
742
+ const parameterized = candidates.filter((def) => !carriesOwnTemplateArguments(def));
743
+ return parameterized.length === 1 ? parameterized[0] : undefined;
744
+ }
745
+ /** Memo for {@link bindsAnyCrossFileClass}, keyed by index bundle then module
746
+ * scope. One bundle per model, so the outer WeakMap releases with it. */
747
+ const crossFileClassChannelByBundle = new WeakMap();
748
+ /**
749
+ * Does the FILE containing `scopeId` bind, at its module scope, any class-like
750
+ * definition declared in a DIFFERENT file?
751
+ *
752
+ * This is the question "is a name's absence from this file's scope chain
753
+ * evidence of anything", and it has to be asked of the data because the answer
754
+ * differs per language while the scope model records no fact that says which.
755
+ * Both halves were MEASURED on this pipeline, not assumed:
756
+ *
757
+ * - A C++ `#include` materializes NO binding. Two files declaring `Repo`, one
758
+ * of them `#include`d by the referencing file, resolves to NEITHER — the
759
+ * include contributed nothing and the ambiguity was decided by the
760
+ * workspace-wide index alone. So a C++ file's chain binds nothing
761
+ * cross-file, and the index is the only channel it has.
762
+ * - A TypeScript `import` does bind, and so does a C# `using` (through the
763
+ * accessible-namespace channel).
764
+ *
765
+ * So "the chain does not bind `Map`" is real evidence in a TypeScript file and
766
+ * no evidence at all in a C++ one. Asking the data which kind of file this is
767
+ * keeps the rule out of the business of naming languages (AGENTS.md R6).
768
+ *
769
+ * FAILS TOWARD PERMISSIVE. `false` — no module scope, no file path, nothing
770
+ * cross-file bound — restores exactly the import-blind behaviour that predates
771
+ * this check, so every way it can be wrong costs a wrong edge that already
772
+ * existed rather than a working edge that did not.
773
+ */
774
+ function bindsAnyCrossFileClass(scopeId, scopes) {
775
+ const moduleScopeId = moduleScopeIdOf(scopeId, scopes);
776
+ if (moduleScopeId === null)
777
+ return false;
778
+ let byScope = crossFileClassChannelByBundle.get(scopes);
779
+ if (byScope === undefined) {
780
+ byScope = new Map();
781
+ crossFileClassChannelByBundle.set(scopes, byScope);
782
+ }
783
+ const memo = byScope.get(moduleScopeId);
784
+ if (memo !== undefined)
785
+ return memo;
786
+ const answer = scanForCrossFileClass(moduleScopeId, scopes);
787
+ byScope.set(moduleScopeId, answer);
788
+ return answer;
789
+ }
790
+ /**
791
+ * The uncached scan behind {@link bindsAnyCrossFileClass}. Answers on the FIRST
792
+ * hit, so a file with a wide `export *` surface stops at its first imported
793
+ * class rather than walking the surface; a file with none is walked in full, but
794
+ * its module scope then holds only its own declarations.
795
+ *
796
+ * Reads the binding CHANNELS rather than asking `lookupBindingsAt` once per
797
+ * name, because the question is existential and the per-name route answers a
798
+ * question it does not need: a module scope activates the accessibility-gated
799
+ * namespace channel, so every one of N bound names re-probed all K accessible
800
+ * namespaces (75.6 ms for one C#-shaped file at N=5,000, K=1,000) and paid
801
+ * `lookupBindingsAt`'s merge allocation each time. The population considered is
802
+ * identical — the two per-scope channels' own buckets, plus the namespace and
803
+ * workspace channels under exactly the names those two bind.
804
+ */
805
+ function scanForCrossFileClass(moduleScopeId, scopes) {
806
+ const filePath = scopes.scopeTree.getScope(moduleScopeId)?.filePath;
807
+ if (filePath === undefined)
808
+ return false;
809
+ const bindsCrossFileClass = (refs) => refs !== undefined &&
810
+ refs.some((ref) => isClassLike(ref.def.type) && ref.def.filePath !== filePath);
811
+ // The two per-scope channels, read as whole buckets. An ordinary import lands
812
+ // here, so this is where the early exit usually fires.
813
+ const finalized = scopes.bindings.get(moduleScopeId);
814
+ const augmented = scopes.bindingAugmentations.get(moduleScopeId);
815
+ for (const channel of [finalized, augmented]) {
816
+ for (const refs of channel?.values() ?? []) {
817
+ if (bindsCrossFileClass(refs))
818
+ return true;
819
+ }
820
+ }
821
+ const boundNameCount = (finalized?.size ?? 0) + (augmented?.size ?? 0);
822
+ if (boundNameCount === 0)
823
+ return false;
824
+ const bindsName = (name) => finalized?.has(name) === true || augmented?.has(name) === true;
825
+ // Materialized once, not per channel — `namesAtScope` allocates when both
826
+ // per-scope channels are populated.
827
+ let boundNames;
828
+ const namesBoundHere = () => (boundNames ??= [...namesAtScope(moduleScopeId, scopes)]);
829
+ // The accessibility-gated namespace channel: ONE lookup per accessible
830
+ // namespace, then whichever of the two sides is smaller is the one iterated —
831
+ // so neither a namespace with a large type table nor a file with many bound
832
+ // names can reintroduce the product.
833
+ for (const ns of scopes.accessibleNamespacesByScope?.get(moduleScopeId) ?? []) {
834
+ const inNamespace = scopes.namespaceFqnBindings?.get(ns);
835
+ if (inNamespace === undefined || inNamespace.size === 0)
836
+ continue;
837
+ if (inNamespace.size <= boundNameCount) {
838
+ for (const [name, refs] of inNamespace) {
839
+ if (bindsName(name) && bindsCrossFileClass(refs))
840
+ return true;
841
+ }
842
+ }
843
+ else {
844
+ for (const name of namesBoundHere()) {
845
+ if (bindsCrossFileClass(inNamespace.get(name)))
846
+ return true;
847
+ }
848
+ }
849
+ }
850
+ // The scope-independent workspace channel is keyed by name alone and has no
851
+ // per-scope bucket to walk, so it stays a probe per bound name.
852
+ const workspace = scopes.workspaceFqnBindings;
853
+ if (workspace !== undefined && workspace.size > 0) {
854
+ for (const name of namesBoundHere()) {
855
+ if (bindsCrossFileClass(workspace.get(name)))
856
+ return true;
857
+ }
858
+ }
859
+ return false;
860
+ }
861
+ /**
862
+ * Resolve a class-like binding for a declared type name, tolerating a spelling
863
+ * that carries TYPE ARGUMENTS (`Repo<User>`, `Vec<int>`) where the declaration
864
+ * itself is registered under the bare base name.
865
+ *
866
+ * Two normalizations, and they are not the same thing:
867
+ *
868
+ * 1. DECORATION stripping (`stripDecoration`, opt-in — see the parameter).
869
+ * Peels type-PRESERVING wrappers (`*T`, `const T&`) off the name.
870
+ * 2. Type-argument ERASURE (unconditional, and the wider of the two).
871
+ * `Repo<User>` → `Repo`. This is what actually widens what binds, because
872
+ * it makes one declaration answer for EVERY instantiation of it — right
873
+ * for a language where a generic class has a single declaration, and a
874
+ * hazard where it does not, which is why the exact-argument match runs
875
+ * first and why the base-name route below refuses to return a
876
+ * declaration that pinned its own arguments.
877
+ *
878
+ * Order: exact spelling → exact type-argument match (lexically visible
879
+ * candidates first, workspace-wide index second) → base name.
880
+ */
881
+ function resolveClassBindingForName(scopeId, rawClassName, scopes,
882
+ /**
883
+ * OPT-IN, and it governs (1) only — argument erasure happens either way.
884
+ * `findClassBindingInScope`'s own docstring explains the opt-in: a name that
885
+ * previously bound nothing starts binding, which SUPPRESSES the
886
+ * `?? otherResolver(...)` fallbacks several callers rely on.
887
+ *
888
+ * THE RULE, not a roll-call of who currently passes it (that list has been
889
+ * appended to once per round of this work and is stale the moment it is
890
+ * written): pass it from a receiver-TYPING site, and only where the site
891
+ * already forwarded the same `stripTypePreservingDecoration` to the bare
892
+ * lookup — so a Go pointer receiver keeps resolving exactly as it did. A site
893
+ * that has never stripped must keep calling without it, because starting to
894
+ * strip is what suppresses its fallback.
895
+ */
896
+ stripDecoration) {
897
+ const direct = findClassBindingInScope(scopeId, rawClassName, scopes, stripDecoration);
898
+ if (direct !== undefined)
899
+ return direct;
900
+ if (!rawClassName.includes('<'))
901
+ return undefined;
902
+ const baseName = (0, template_arguments_js_1.stripTemplateArguments)(rawClassName).replace(/\s+/g, '');
903
+ if (baseName.length === 0)
904
+ return undefined;
905
+ // The class-like defs the SCOPE CHAIN binds for the base name. Computed once
906
+ // and used twice — it is the lexical half of "what can the base name see from
907
+ // here" AND ground (1) of the erasure rule below, and the two asked for it
908
+ // separately, bottoming out in the same walk for a third of the cost of every
909
+ // lookup whose declared type carries type arguments.
910
+ const lexical = lexicalClassBindingsInScope(scopeId, baseName, scopes);
911
+ const wantedArgs = (0, template_arguments_js_1.extractTemplateArguments)(rawClassName)?.map(normalizeTemplateArgToken);
912
+ if (wantedArgs !== undefined && wantedArgs.length > 0) {
913
+ // LEXICAL FIRST. The workspace-wide index is not scoped, so matching against
914
+ // it up front let a field inside `namespace N` be answered by the GLOBAL
915
+ // `Box<bool>` — or, when both namespaces declare one, by neither: two
916
+ // matches, a decline, and a fall through to whatever base-name declaration
917
+ // the walk reached first. Candidates the scope chain actually offers are
918
+ // ranked ahead of it, exactly as every other lookup in this file does.
919
+ const lexicalMatches = matchingTemplateArguments(classBindingsVisibleFrom(lexical, baseName, scopes), wantedArgs);
920
+ if (lexicalMatches.length === 1)
921
+ return lexicalMatches[0];
922
+ if (lexicalMatches.length === 0) {
923
+ // Workspace-wide fallback — consulted ONLY when the scope chain offered no
924
+ // exact match, which is how a declaration specialized in a different file
925
+ // than the one instantiating it still binds.
926
+ const indexMatches = matchingTemplateArguments(classDefsByQualifiedName(baseName, scopes), wantedArgs);
927
+ if (indexMatches.length === 1)
928
+ return indexMatches[0];
929
+ }
930
+ }
931
+ // ── Base-name route ────────────────────────────────────────────────────────
932
+ // Nothing matched the arguments as written, so what is left to find is the
933
+ // declaration written against its PARAMETERS — the one instantiation-agnostic
934
+ // declaration the erasure is entitled to reach.
935
+ return resolveErasedBaseName(scopeId, baseName, scopes, lexical);
936
+ }
937
+ /**
938
+ * The declaration an ERASED base name is entitled to reach — the counterpart of
939
+ * `findClassBindingInScope` for a name that lost its type arguments, and the one
940
+ * place the grounding rule for that erasure lives.
941
+ *
942
+ * GROUNDING is the whole difference between a fix and a fabrication. Erasure
943
+ * makes ONE declaration answer for EVERY instantiation of a name, so reaching it
944
+ * by NAME ALONE is the widest step in this file: it is why `Map<string, User>`
945
+ * bound a workspace `class Map` the file cannot see, and why a third-party
946
+ * `Mapped[User]` bound an unrelated workspace `class Mapped` — a family of
947
+ * confident wrong edges the language interpreters have been holding back with
948
+ * deny-lists over an open universe of names. The name is not evidence. One of
949
+ * four grounds must connect the site to the declaration, strongest first.
950
+ */
951
+ function resolveErasedBaseName(scopeId, baseName, scopes,
952
+ /**
953
+ * Ground (1) below, already computed: {@link lexicalClassBindingsInScope} for
954
+ * `baseName` at `scopeId`. A parameter rather than a call because the only
955
+ * caller needs the same list for its exact-argument match, and computing it
956
+ * twice walked the scope chain twice.
957
+ */
958
+ lexical) {
959
+ // (1) THE SCOPE CHAIN binds the base name — a local, an import, a wildcard, a
960
+ // namespace sibling. The file demonstrably sees a declaration by that name, so
961
+ // erasing to it is what the source meant.
962
+ if (lexical.length > 0) {
963
+ const nearest = lexical[0];
964
+ // The walk landed on a declaration that pinned its own arguments — arguments
965
+ // the branch above just proved are NOT the ones written. It won on nothing
966
+ // but being reached first: `Vec<int> vi` bound the `Vec<bool>`
967
+ // specialization when the specialization happened to be declared above the
968
+ // primary template, and the primary when it did not. Source order deciding a
969
+ // call target is a wrong edge, not a missing one. Re-decide over the same
970
+ // visible candidates with those declarations removed.
971
+ return carriesOwnTemplateArguments(nearest)
972
+ ? theInstantiationAgnosticDeclaration(lexical)
973
+ : nearest;
974
+ }
975
+ // Nothing lexical. Both remaining grounds read the workspace-wide qualified-
976
+ // name index, which consults no scope, no import and no module — so each one
977
+ // has to supply the connection the index itself cannot.
978
+ const indexed = classDefsByQualifiedName(baseName, scopes);
979
+ // (2) THE DECLARATION IS IN THIS VERY FILE. A same-file declaration is visible
980
+ // to the site in every language — no import, no `using`, no `#include` — which
981
+ // is exactly what makes this ground language-neutral rather than a guess. It
982
+ // is also load-bearing rather than theoretical: a member typed `ns::Repo<User>`
983
+ // resolves through here, because the qualifier is dropped at capture and a
984
+ // sibling NAMESPACE is not on the file's scope chain.
985
+ const siteFile = scopes.scopeTree.getScope(scopeId)?.filePath;
986
+ const sameFile = siteFile === undefined ? [] : indexed.filter((def) => def.filePath === siteFile);
987
+ if (sameFile.length > 0)
988
+ return theInstantiationAgnosticDeclaration(sameFile);
989
+ // (3) THE INDEX PROVES THE NAME IS A TEMPLATE FAMILY — some declaration under
990
+ // it pins its own arguments. That is the same evidence the exact-argument
991
+ // index match above already acts on, and acting on it in only one direction
992
+ // was incoherent: in one measured fixture `Vec<bool>` bound the cross-file
993
+ // SPECIALIZATION through the index while `Vec<int>` bound nothing, though both
994
+ // are equally import-blind and the primary template is the only declaration
995
+ // that can answer `int`.
996
+ //
997
+ // (4) …or THE FILE HAS NO CROSS-FILE CHANNEL to be absent from, in which case
998
+ // the index is not a shortcut around the scope chain — it is the only channel
999
+ // that file has, and refusing it deletes every cross-file generic in the
1000
+ // languages whose visibility is not lexical. Measured, both directions: a C++
1001
+ // `#include` binds nothing, so `Repo<User>` in a `.cpp` reaches its header
1002
+ // declaration ONLY here; a TypeScript `import` binds, so a file that imports
1003
+ // anything and still cannot see `Map` genuinely cannot see it.
1004
+ //
1005
+ // Between them these two grounds are what separates the fix from the
1006
+ // fabrication: `Map`, `Queue`, `Deque` in a file with a working import channel
1007
+ // offer nothing but a spelling, and now get nothing.
1008
+ if (indexed.some(carriesOwnTemplateArguments) || !bindsAnyCrossFileClass(scopeId, scopes)) {
1009
+ return theInstantiationAgnosticDeclaration(indexed);
1010
+ }
1011
+ return undefined;
1012
+ }
1013
+ /**
1014
+ * Resolve a class-like inheritance target using the shared inheritance
1015
+ * resolution chain. Keeps pre-emitted heritage edges and language-specific
1016
+ * consumers of `inherits` sites aligned.
1017
+ */
1018
+ function resolveInheritanceBaseInScope(startScope, baseName, scopes, rawQualifiedName, enclosingClassDef) {
1019
+ // #1982: when the source wrote a qualified base (`Other::Inner`), resolve it
1020
+ // against the full-path QualifiedNameIndex FIRST, so a same-tail nested base
1021
+ // binds to the matching sibling instead of the first-inserted one that the
1022
+ // simple-tail scope walk picks. Falls through to the existing walk when the
1023
+ // base is unqualified, unknown, or the qualified lookup can't pick a unique
1024
+ // winner — so unqualified bases and the cross-file single-candidate case are
1025
+ // unchanged. `enclosingClassDef` (the deriving class) is threaded from the
1026
+ // caller to skip a redundant enclosing-class walk (#1982 perf).
1027
+ if (rawQualifiedName !== undefined) {
1028
+ const qualified = resolveQualifiedInheritanceBase(startScope, rawQualifiedName, scopes, enclosingClassDef);
1029
+ if (qualified !== undefined)
1030
+ return qualified;
1031
+ }
1032
+ return (findClassBindingInScope(startScope, baseName, scopes) ??
1033
+ resolveAmbiguousInheritanceBaseViaImports(startScope, baseName, scopes));
1034
+ }
1035
+ /**
1036
+ * Resolve a qualified inheritance base (`Other::Inner`, `ns::Base`) against the
1037
+ * full-path `QualifiedNameIndex` (keyed by `def.qualifiedName`, which carries
1038
+ * the promoted dotted path post-`populateOwners`). Tries the referencing site's
1039
+ * enclosing-scope segments as progressive prefixes (longest first) before the
1040
+ * root-anchored qualifier, so a *relative* base like `Outer::Inner` written
1041
+ * inside `namespace NS` resolves to the root-anchored key `NS.Outer.Inner`.
1042
+ * Returns a unique class-like def, or `undefined` when the base is unqualified,
1043
+ * unknown, or genuinely ambiguous at a key (refuse-on-tie — never guess; a
1044
+ * wrong EXTENDS edge silently corrupts impact analysis).
1045
+ */
1046
+ function resolveQualifiedInheritanceBase(startScope, rawQualifiedName, scopes, enclosingClassDef) {
1047
+ const normalized = (0, qualified_name_js_1.stripTrailingTypeArguments)((0, qualified_name_js_1.normalizeQualifiedName)(rawQualifiedName));
1048
+ // No qualifier after normalization → nothing the simple-tail walk doesn't do.
1049
+ if (normalized.length === 0 || !normalized.includes('.'))
1050
+ return undefined;
1051
+ // #1982: a root-anchored base (`::Net::X`) names the GLOBAL scope, so it must
1052
+ // NOT be prefixed with the referencing site's enclosing segments — try only
1053
+ // the root-anchored key. normalizeQualifiedName strips the leading `::`, so
1054
+ // detect the anchor on the raw text (after leading whitespace).
1055
+ const isRootAnchored = /^\s*::/.test(rawQualifiedName);
1056
+ const enclosing = isRootAnchored
1057
+ ? []
1058
+ : enclosingScopeSegments(startScope, scopes, enclosingClassDef);
1059
+ // Candidate keys: longest enclosing prefix first for *relative* qualified
1060
+ // bases (`Outer.Inner` inside `NS.Outer.Derived` → `NS.Outer.Inner`). When the
1061
+ // qualifier names a *different* namespace than the enclosing scope (`new B.Foo()`
1062
+ // inside `namespace A` → `B.Foo`, not `A.Foo`), try the raw normalized key
1063
+ // FIRST so same-tail local bindings don't win (#2046 / #1991).
1064
+ const normParts = (0, qualified_name_js_1.splitQualifiedName)(normalized);
1065
+ const isRelativeToEnclosing = enclosing.length > 0 &&
1066
+ normParts.length > 0 &&
1067
+ normParts[0] === enclosing[enclosing.length - 1];
1068
+ const keys = [];
1069
+ if (!isRelativeToEnclosing) {
1070
+ keys.push(normalized);
1071
+ }
1072
+ for (let i = enclosing.length; i >= 1; i--) {
1073
+ keys.push([...enclosing.slice(0, i), normalized].join('.'));
1074
+ }
1075
+ if (!keys.includes(normalized)) {
1076
+ keys.push(normalized);
1077
+ }
1078
+ for (const key of keys) {
1079
+ const ids = scopes.qualifiedNames.get(key);
1080
+ if (ids.length === 0)
1081
+ continue;
1082
+ let unique;
1083
+ let count = 0;
1084
+ for (const id of ids) {
1085
+ const def = scopes.defs.get(id);
1086
+ if (def !== undefined && isClassLike(def.type)) {
1087
+ unique = def;
1088
+ count++;
1089
+ }
1090
+ }
1091
+ if (count === 1)
1092
+ return unique;
1093
+ if (count > 1) {
1094
+ // #1993: same-tail bases collide at this namespace-omitted key (`NS1::A::Inner`
1095
+ // and `NS2::A::Inner` both key `A.Inner`). Break the tie with the bridge's
1096
+ // `namespacePrefix` sidecar — prefer the candidate in the SAME enclosing
1097
+ // namespace as the deriving class. Bridge-held: `def.qualifiedName` and the
1098
+ // index keys are untouched; still refuse when the sidecar can't pick a unique.
1099
+ const childPrefix = enclosingClassDef?.namespacePrefix;
1100
+ if (childPrefix !== undefined && childPrefix.length > 0) {
1101
+ let nsUnique;
1102
+ let nsCount = 0;
1103
+ for (const id of ids) {
1104
+ const def = scopes.defs.get(id);
1105
+ if (def !== undefined && isClassLike(def.type) && def.namespacePrefix === childPrefix) {
1106
+ nsUnique = def;
1107
+ nsCount++;
1108
+ }
1109
+ }
1110
+ if (nsCount === 1)
1111
+ return nsUnique;
1112
+ }
1113
+ return undefined; // genuine tie → refuse, don't guess
1114
+ }
1115
+ }
1116
+ // Qualifier-vs-sidecar fallback (#2046). Languages whose class `qualifiedName`
1117
+ // is the SIMPLE name (C#) never populate a qualified key in the index, so the
1118
+ // keyed loop above can't see `B.Foo`. Resolve the simple TAIL and break the
1119
+ // same-tail collision by matching the explicit qualifier (`B`) against each
1120
+ // candidate's `namespacePrefix` sidecar. Commit only on a unique match — a
1121
+ // still-ambiguous qualifier refuses (never guesses a wrong EXTENDS/CALLS edge).
1122
+ const tail = normParts[normParts.length - 1];
1123
+ const qualifier = normParts.slice(0, -1).join('.');
1124
+ if (tail !== undefined && qualifier.length > 0) {
1125
+ const tailIds = scopes.qualifiedNames.get(tail);
1126
+ let qUnique;
1127
+ let qCount = 0;
1128
+ for (const id of tailIds) {
1129
+ const def = scopes.defs.get(id);
1130
+ if (def === undefined || !isClassLike(def.type))
1131
+ continue;
1132
+ const np = def.namespacePrefix;
1133
+ if (np === undefined || np.length === 0)
1134
+ continue;
1135
+ if (np === qualifier || np.endsWith(`.${qualifier}`)) {
1136
+ qUnique = def;
1137
+ qCount++;
1138
+ }
1139
+ }
1140
+ if (qCount === 1)
1141
+ return qUnique;
1142
+ }
1143
+ return undefined;
1144
+ }
1145
+ /**
1146
+ * Enclosing scope segments of an inheritance site, derived from the deriving
1147
+ * (child) class def's `qualifiedName` minus its own tail. For child
1148
+ * `NS.Other.Derived` this is `['NS', 'Other']`; empty for a file-scope child.
1149
+ * Used to build progressive-prefix lookup keys for relative qualified bases.
1150
+ */
1151
+ function enclosingScopeSegments(startScope, scopes, enclosingClassDef) {
1152
+ // Reuse the caller-provided deriving class when available (#1982 perf); only
1153
+ // walk the scope chain when it wasn't threaded in.
1154
+ const child = enclosingClassDef ?? findEnclosingClassDef(startScope, scopes);
1155
+ const q = child?.qualifiedName;
1156
+ if (q === undefined || q.length === 0)
1157
+ return [];
1158
+ const segs = q.split('.').filter(Boolean);
1159
+ return segs.slice(0, -1);
1160
+ }
1161
+ /**
1162
+ * Import/include-aware disambiguation for an *ambiguous* class-like base
1163
+ * name. Engages ONLY as a fallback after `findClassBindingInScope` has
1164
+ * already returned `undefined` — i.e. the scope-chain walk and the
1165
+ * single-match `qualifiedNames` fast paths could not pick a winner because
1166
+ * several same-named class-like defs exist (e.g. two `class Handler`s in
1167
+ * different headers/namespaces).
1168
+ *
1169
+ * Disambiguates by the referencing file's import graph: the enclosing
1170
+ * module scope's finalized `ImportEdge[]` (C++ `#include`, C# `using`, etc.)
1171
+ * each carry the exporting file in `targetFile`. A candidate whose defining
1172
+ * file is brought in by one of those edges is preferred. Resolution is
1173
+ * tiered, strictest first, and only commits when EXACTLY ONE candidate
1174
+ * survives a tier — so a still-ambiguous name keeps the historical
1175
+ * "return undefined" refusal:
1176
+ *
1177
+ * 1. Exact file match — candidate.filePath === an import's `targetFile`
1178
+ * (covers C++ `#include "handler_a.h"` → that header's class).
1179
+ * 2. Same-directory match — candidate.filePath sits in the same directory
1180
+ * as some import target file (covers C# `using MyApp.Models;`, where the
1181
+ * namespace import resolves to ONE representative file in the namespace's
1182
+ * directory, not necessarily the file declaring the referenced type).
1183
+ *
1184
+ * Language-neutral: keyed only on the finalized import edges and the
1185
+ * candidate defs' `filePath`. Returns `undefined` (preserving refusal) when
1186
+ * the name is single-match-resolvable already (never reached — caller gates
1187
+ * on `findClassBindingInScope` miss), when no import disambiguates, or when
1188
+ * a tier leaves more than one survivor.
1189
+ */
1190
+ function resolveAmbiguousInheritanceBaseViaImports(startScope, baseName, scopes) {
1191
+ // Gather the class-like candidates that share this simple name. Defs are
1192
+ // indexed by their `qualifiedName` in `qualifiedNames`; for languages whose
1193
+ // class qualifiedName IS the simple name (C++, C#, etc.) this is the full
1194
+ // candidate set. A single candidate is not "ambiguous" — leave it to the
1195
+ // existing single-match fast path (this fallback shouldn't have been called).
1196
+ const candidateIds = scopes.qualifiedNames.get(baseName);
1197
+ if (candidateIds.length < 2)
1198
+ return undefined;
1199
+ const candidates = [];
1200
+ for (const id of candidateIds) {
1201
+ const def = scopes.defs.get(id);
1202
+ if (def !== undefined && isClassLike(def.type))
1203
+ candidates.push(def);
1204
+ }
1205
+ if (candidates.length < 2)
1206
+ return undefined;
1207
+ // Collect the exporting files imported by the referencing file's enclosing
1208
+ // module scope (the chain may carry function-local imports too, but the
1209
+ // module scope is where `#include` / `using` land).
1210
+ const moduleScopeId = moduleScopeIdOf(startScope, scopes);
1211
+ if (moduleScopeId === null)
1212
+ return undefined;
1213
+ const importEdges = scopes.imports.get(moduleScopeId);
1214
+ if (importEdges === undefined || importEdges.length === 0)
1215
+ return undefined;
1216
+ const importedFiles = new Set();
1217
+ const importedDirs = new Set();
1218
+ for (const edge of importEdges) {
1219
+ if (edge.targetFile === null)
1220
+ continue;
1221
+ importedFiles.add(edge.targetFile);
1222
+ importedDirs.add(dirnameOf(edge.targetFile));
1223
+ }
1224
+ if (importedFiles.size === 0)
1225
+ return undefined;
1226
+ // Tier 1 — exact file match (C++ `#include "handler_a.h"`).
1227
+ const exact = candidates.filter((c) => importedFiles.has(c.filePath));
1228
+ if (exact.length === 1)
1229
+ return exact[0];
1230
+ if (exact.length > 1)
1231
+ return undefined; // still ambiguous → refuse
1232
+ // Tier 2 — same-directory match (C# namespace `using`, where the namespace
1233
+ // import resolves to one representative file in the namespace's directory).
1234
+ const sameDir = candidates.filter((c) => importedDirs.has(dirnameOf(c.filePath)));
1235
+ if (sameDir.length === 1)
1236
+ return sameDir[0];
1237
+ return undefined;
1238
+ }
1239
+ /**
1240
+ * Directory portion of a forward-slash workspace-relative path. Returns `''`
1241
+ * for a bare filename (no directory). Workspace paths are always normalized to
1242
+ * `/` separators upstream, so a simple `lastIndexOf('/')` is sufficient and
1243
+ * keeps this dependency-free.
1244
+ */
1245
+ function dirnameOf(filePath) {
1246
+ const idx = filePath.lastIndexOf('/');
1247
+ return idx === -1 ? '' : filePath.slice(0, idx);
1248
+ }
1249
+ /**
1250
+ * Predicate for value-receiver bridge: the labels for which
1251
+ * `reconcileOwnership` registers methods/fields under the def's
1252
+ * `nodeId` as the `ownerId`. Explicit allowlist so future NodeLabel
1253
+ * additions (Module, Namespace, TypeAlias, EnumMember, etc.) do NOT
1254
+ * silently widen the bridge — adding a new ownerable label requires
1255
+ * touching both this predicate and `reconcileOwnership`.
1256
+ *
1257
+ * See: `scope-resolution/pipeline/reconcile-ownership.ts` Property /
1258
+ * Variable / Const / Static registration block.
1259
+ */
1260
+ function isOwnableValueLabel(t) {
1261
+ return t === 'Const' || t === 'Variable' || t === 'Property' || t === 'Static';
1262
+ }
1263
+ /**
1264
+ * Look up a value-binding (Const/Variable/Property/Static) by name in
1265
+ * the given scope's chain. Used by the value-receiver-owner bridge
1266
+ * for object-literal services such as:
1267
+ *
1268
+ * export const fooService = { getUser(id) {...} };
1269
+ *
1270
+ * where `fooService` is a `Const`/`Variable` whose `nodeId` is the
1271
+ * `ownerId` of the member method. Neither `findClassBindingInScope`
1272
+ * (rejects non-class-like) nor `findReceiverTypeBinding` (no typeBinding
1273
+ * for an unannotated literal) finds it.
1274
+ *
1275
+ * Mirrors `findClassBindingInScope` exactly; only the accepted def-type
1276
+ * predicate differs.
1277
+ */
1278
+ function findValueBindingInScope(startScope, receiverName, scopes) {
1279
+ return walkScopeChain(startScope, receiverName, scopes, (def) => isOwnableValueLabel(def.type));
1280
+ }
1281
+ /**
1282
+ * Generic scope-chain walker. Walks from `startScope` toward the root,
1283
+ * consulting both the local `scope.bindings` channel and the dual-source
1284
+ * `lookupBindingsAt` view (finalized + augmented). At each scope, local
1285
+ * bindings are exhausted BEFORE imported/augmented bindings — preserves
1286
+ * JavaScript-style lexical scoping where a local `const x` shadows an
1287
+ * imported `x` of the same name.
1288
+ *
1289
+ * Returns the first binding `def` matching `predicate`. Cycles in the
1290
+ * scope graph terminate the walk (defensive — should not occur in
1291
+ * well-formed inputs).
1292
+ */
1293
+ function walkScopeChain(startScope, name, scopes, predicate) {
1294
+ let currentId = startScope;
1295
+ const visited = new Set();
1296
+ while (currentId !== null) {
1297
+ if (visited.has(currentId))
1298
+ return undefined;
1299
+ visited.add(currentId);
1300
+ const scope = scopes.scopeTree.getScope(currentId);
1301
+ if (scope === undefined)
1302
+ return undefined;
1303
+ // `Object` scopes (object/record literal bodies) are a hoist
1304
+ // boundary only -- their members are reachable via property access,
1305
+ // never bare identifiers, so they contribute nothing to lookup
1306
+ // (#2545/#2551). Still traverse past to the parent.
1307
+ if (scope.kind !== 'Object') {
1308
+ // Local first: a `const x` in this scope shadows any imported `x`.
1309
+ const localBindings = scope.bindings.get(name);
1310
+ if (localBindings !== undefined) {
1311
+ for (const b of localBindings) {
1312
+ if (predicate(b.def))
1313
+ return b.def;
1314
+ }
1315
+ }
1316
+ // Then imported/augmented bindings — only consulted when no local match.
1317
+ const importedBindings = lookupBindingsAt(currentId, name, scopes);
1318
+ for (const b of importedBindings) {
1319
+ if (predicate(b.def))
1320
+ return b.def;
1321
+ }
1322
+ }
1323
+ currentId = scope.parent;
1324
+ }
1325
+ return undefined;
1326
+ }
1327
+ /**
1328
+ * Look up a callable (Function/Method/Constructor) by name in the
1329
+ * given scope's chain. Uses the dual-source pattern (scope.bindings +
1330
+ * `lookupBindingsAt` for finalized + augmented) so cross-file
1331
+ * imports are visible — without it free calls to imported functions
1332
+ * never resolve via the post-pass.
1333
+ *
1334
+ * Mirrors `findClassBindingInScope` exactly; only the accepted
1335
+ * def-type predicate differs.
1336
+ */
1337
+ function findCallableBindingInScope(startScope, callableName, scopes) {
1338
+ return findAllCallableBindingsInScope(startScope, callableName, scopes)[0];
1339
+ }
1340
+ function collectCallableBindingCandidates(sources) {
1341
+ const byNodeId = new Map();
1342
+ for (const source of sources) {
1343
+ if (source === undefined)
1344
+ continue;
1345
+ for (const binding of source) {
1346
+ const def = binding.def;
1347
+ if (def.type !== 'Function' && def.type !== 'Method' && def.type !== 'Constructor')
1348
+ continue;
1349
+ const existing = byNodeId.get(def.nodeId);
1350
+ if (existing === undefined) {
1351
+ byNodeId.set(def.nodeId, { def, bindings: [binding] });
1352
+ }
1353
+ else {
1354
+ existing.bindings.push(binding);
1355
+ }
1356
+ }
1357
+ }
1358
+ return [...byNodeId.values()];
1359
+ }
1360
+ /**
1361
+ * Binding-aware callable lookup for consumers that need visibility evidence.
1362
+ * Unlike `lookupBindingsAt`, duplicate definitions retain every binding path,
1363
+ * so a weaker augmentation can contribute provenance even when a finalized
1364
+ * binding remains the candidate's canonical definition.
1365
+ */
1366
+ function findAllCallableBindingCandidatesInScope(startScope, callableName, scopes) {
1367
+ let currentId = startScope;
1368
+ const visited = new Set();
1369
+ while (currentId !== null) {
1370
+ if (visited.has(currentId))
1371
+ return [];
1372
+ visited.add(currentId);
1373
+ const scope = scopes.scopeTree.getScope(currentId);
1374
+ if (scope === undefined)
1375
+ return [];
1376
+ if (scope.kind !== 'Object') {
1377
+ const lexical = collectCallableBindingCandidates([scope.bindings.get(callableName)]);
1378
+ if (lexical.length > 0)
1379
+ return lexical;
1380
+ const candidates = collectCallableBindingCandidates([
1381
+ scopes.bindings.get(currentId)?.get(callableName),
1382
+ scopes.bindingAugmentations.get(currentId)?.get(callableName),
1383
+ collectNamespaceFqnBindings(currentId, callableName, scopes),
1384
+ scopes.workspaceFqnBindings?.get(callableName),
1385
+ ]);
1386
+ if (candidates.length > 0)
1387
+ return candidates;
1388
+ }
1389
+ currentId = scope.parent;
1390
+ }
1391
+ return [];
1392
+ }
1393
+ /**
1394
+ * Look up all callable bindings (Function/Method/Constructor) by name
1395
+ * from the nearest scope in the chain that binds `callableName`.
1396
+ *
1397
+ * Preserves the original scope-walk boundary used by
1398
+ * `findCallableBindingInScope`: once any callable binding is found in a
1399
+ * scope, outer scopes are not consulted.
1400
+ */
1401
+ /**
1402
+ * Every definition visible for `name` at the NEAREST scope that binds it,
1403
+ * filtered by `predicate` and deduped by `nodeId`.
1404
+ *
1405
+ * THE shared "collect all at the nearest binding scope" walk. `walkScopeChain`
1406
+ * answers the first-match question; this answers the how-many question, which is
1407
+ * what a caller needs before it can decline on ambiguity.
1408
+ *
1409
+ * Stops at the first scope that binds the name at all: an inner binding SHADOWS
1410
+ * an outer one, so continuing would report a shadowed outer definition as a
1411
+ * competing candidate and decline a name that is unambiguous at this point.
1412
+ *
1413
+ * Returns `[]` on a cycle or a missing scope. That is deliberate and matters:
1414
+ * an earlier copy of this walk `break`-ed instead and fell through to a
1415
+ * qualified-name fallback, so the same malformed input produced a different
1416
+ * answer depending on which copy the caller happened to reach.
1417
+ */
1418
+ function findAllBindingsInScope(startScope, name, scopes, predicate) {
1419
+ let currentId = startScope;
1420
+ const visited = new Set();
1421
+ while (currentId !== null) {
1422
+ if (visited.has(currentId))
1423
+ return [];
1424
+ visited.add(currentId);
1425
+ const scope = scopes.scopeTree.getScope(currentId);
1426
+ if (scope === undefined)
1427
+ return [];
1428
+ // `Object` scopes are a hoist boundary only -- see walkScopeChain's
1429
+ // comment (#2545/#2551). Skip lookup here, still traverse to parent.
1430
+ if (scope.kind !== 'Object') {
1431
+ const out = [];
1432
+ const seen = new Set();
1433
+ const push = (def) => {
1434
+ if (!predicate(def))
1435
+ return;
1436
+ if (seen.has(def.nodeId))
1437
+ return;
1438
+ seen.add(def.nodeId);
1439
+ out.push(def);
1440
+ };
1441
+ // Local first: a binding in this scope shadows an imported one.
1442
+ for (const b of scope.bindings.get(name) ?? [])
1443
+ push(b.def);
1444
+ for (const b of lookupBindingsAt(currentId, name, scopes))
1445
+ push(b.def);
1446
+ if (out.length > 0)
1447
+ return out;
1448
+ }
1449
+ currentId = scope.parent;
1450
+ }
1451
+ return [];
1452
+ }
1453
+ function findAllCallableBindingsInScope(startScope, callableName, scopes) {
1454
+ return findAllBindingsInScope(startScope, callableName, scopes, (def) => def.type === 'Function' || def.type === 'Method' || def.type === 'Constructor');
1455
+ }
1456
+ /**
1457
+ * ISO C++ `[basic.lookup.unqual]` §7: ADL is suppressed when ordinary
1458
+ * unqualified lookup finds:
1459
+ * - a name that is NOT a function or function template, OR
1460
+ * - a block-scope function declaration that is NOT a using-declaration.
1461
+ *
1462
+ * Combined walker that stops at the **nearest scope** where `name` has any
1463
+ * binding (callable or non-callable) and returns:
1464
+ * - `callables`: Function/Method/Constructor defs found at that scope
1465
+ * - `nonCallableFound`: a non-function binding was present (variable, class, etc.)
1466
+ * - `blockScopeDeclFound`: a callable was found at a Function or Block scope
1467
+ * (block-scope function declaration that blocks ADL)
1468
+ *
1469
+ * One pass, one stop — no divergence between callable collection and blocker
1470
+ * detection.
1471
+ */
1472
+ function findCallableBindingsAndAdlBlocker(startScope, name, scopes) {
1473
+ let currentId = startScope;
1474
+ const visited = new Set();
1475
+ while (currentId !== null) {
1476
+ if (visited.has(currentId))
1477
+ return { callables: [], nonCallableFound: false, blockScopeDeclFound: false };
1478
+ visited.add(currentId);
1479
+ const scope = scopes.scopeTree.getScope(currentId);
1480
+ if (scope === undefined)
1481
+ return { callables: [], nonCallableFound: false, blockScopeDeclFound: false };
1482
+ const callables = [];
1483
+ const seen = new Set();
1484
+ let nonCallableFound = false;
1485
+ let anyBinding = false;
1486
+ const process = (def) => {
1487
+ anyBinding = true;
1488
+ if (def.type === 'Function' || def.type === 'Method' || def.type === 'Constructor') {
1489
+ if (!seen.has(def.nodeId)) {
1490
+ seen.add(def.nodeId);
1491
+ callables.push(def);
1492
+ }
1493
+ }
1494
+ else {
1495
+ nonCallableFound = true;
1496
+ }
1497
+ };
1498
+ // `Object` scopes are a hoist boundary only (#2545/#2551) -- never
1499
+ // reached by C++'s ADL path in practice (no language reusing this
1500
+ // function emits `@scope.object`), guarded for consistency with the
1501
+ // other scope-chain walkers in this file.
1502
+ if (scope.kind !== 'Object') {
1503
+ const localBindings = scope.bindings.get(name);
1504
+ if (localBindings !== undefined) {
1505
+ for (const b of localBindings) {
1506
+ process(b.def);
1507
+ }
1508
+ }
1509
+ const importedBindings = lookupBindingsAt(currentId, name, scopes);
1510
+ for (const b of importedBindings) {
1511
+ process(b.def);
1512
+ }
1513
+ }
1514
+ if (anyBinding) {
1515
+ // ISO C++: a block-scope function declaration (Function or Block scope)
1516
+ // that is NOT a using-declaration blocks ADL. If we found callables at
1517
+ // a function/block scope, ADL must be suppressed.
1518
+ const blockScopeDeclFound = callables.length > 0 && (scope.kind === 'Function' || scope.kind === 'Block');
1519
+ return { callables, nonCallableFound, blockScopeDeclFound };
1520
+ }
1521
+ currentId = scope.parent;
1522
+ }
1523
+ return { callables: [], nonCallableFound: false, blockScopeDeclFound: false };
1524
+ }
1525
+ /**
1526
+ * Populate `ownerId` on every def structurally owned by a Class
1527
+ * scope — methods (defs in Function scopes whose parent is Class)
1528
+ * and class-body fields (defs directly in Class scopes).
1529
+ *
1530
+ * Generic OO ownership rule. Languages that want richer ownership
1531
+ * (e.g. inner-class qualification) can compose with this as a base
1532
+ * step.
1533
+ *
1534
+ * Mutates `parsed.localDefs` in place via type cast — `SymbolDefinition`
1535
+ * is `readonly` for consumers but the extractor returns plain objects.
1536
+ * Defs are shared by reference between `localDefs` and `Scope.ownedDefs`,
1537
+ * so this single mutation is visible from both sides.
1538
+ */
1539
+ function populateClassOwnedMembers(parsed) {
1540
+ const scopesById = new Map();
1541
+ for (const scope of parsed.scopes)
1542
+ scopesById.set(scope.id, scope);
1543
+ // Promote a def's qualifiedName from `methodName` to `ClassName.methodName`
1544
+ // when the def sits inside a class. Without this, two classes in the
1545
+ // same file that share a method name collide at the graph-bridge lookup
1546
+ // (`node-lookup.ts` keys by (filePath, qualifiedName) and falls back to
1547
+ // simple name only). Python's scope query doesn't emit
1548
+ // `@declaration.qualified_name` for nested methods, so the finalized
1549
+ // defs arrive here with simple names — we stamp the qualifier while
1550
+ // we're already walking class scopes for ownerId.
1551
+ const qualify = (def, classDef) => {
1552
+ const q = def.qualifiedName;
1553
+ if (q === undefined || q.length === 0)
1554
+ return;
1555
+ if (q.includes('.'))
1556
+ return; // already qualified (dotted)
1557
+ // A synthesized anonymous-class def (Java `$`-chain binary name,
1558
+ // #2550/#2555 — `M3$2`, `EnumWrap$Mode$1`) already carries its
1559
+ // COMPLETE name. Prefixing it (`M3.M3$2`) desyncs from the
1560
+ // structure-phase node id (`M3$2.hook`), so same-named methods
1561
+ // across sibling enum-constant bodies collapse onto the first
1562
+ // body's node via the simple-name fallback (empirically caught in
1563
+ // review). Class-like only: `$`-named MEMBERS (legal in JS/TS)
1564
+ // still qualify normally against their class.
1565
+ if (isClassLike(def.type) && q.includes('$'))
1566
+ return;
1567
+ const classQ = classDef.qualifiedName;
1568
+ if (classQ === undefined || classQ.length === 0)
1569
+ return;
1570
+ def.qualifiedName = `${classQ}.${q}`;
1571
+ };
1572
+ // Depth invariant (verified empirically against Python scope-extractor
1573
+ // 2026-04-21): a nested `def helper` declared inside a method body
1574
+ // lives in its OWN Function scope whose parent is the method's Function
1575
+ // scope (not the Class scope). That means the `parentScope.kind ===
1576
+ // 'Class'` branch below only matches DIRECT class-scope children —
1577
+ // method defs themselves — and never stamps arbitrary nested defs with
1578
+ // `ownerId = classDef.nodeId`. If an adversarial reviewer raises this
1579
+ // as a potential false-attribution bug, verify first with a scope dump
1580
+ // on `class U: def save(self): def helper(): ...` — helper.ownerId will
1581
+ // remain undefined. The theoretical concern is real only if the
1582
+ // extractor ever stops creating scopes for inner defs.
1583
+ for (const scope of parsed.scopes) {
1584
+ // Methods: function scope whose parent is a Class scope. Owner is
1585
+ // the parent's class-like def.
1586
+ if (scope.parent !== null) {
1587
+ const parentScope = scopesById.get(scope.parent);
1588
+ if (parentScope !== undefined && parentScope.kind === 'Class') {
1589
+ const classDef = parentScope.ownedDefs.find((d) => isClassLike(d.type));
1590
+ if (classDef !== undefined) {
1591
+ for (const def of scope.ownedDefs) {
1592
+ def.ownerId = classDef.nodeId;
1593
+ qualify(def, classDef);
1594
+ }
1595
+ }
1596
+ }
1597
+ }
1598
+ // Class-body fields: defs directly owned by a Class scope (the
1599
+ // class-like def itself excluded).
1600
+ if (scope.kind === 'Class') {
1601
+ const classDef = scope.ownedDefs.find((d) => isClassLike(d.type));
1602
+ if (classDef !== undefined) {
1603
+ for (const def of scope.ownedDefs) {
1604
+ if (def === classDef)
1605
+ continue;
1606
+ def.ownerId = classDef.nodeId;
1607
+ qualify(def, classDef);
1608
+ }
1609
+ }
1610
+ }
1611
+ }
1612
+ }
1613
+ /**
1614
+ * Tag every def declared inside one or more `Namespace` scopes with its
1615
+ * enclosing-namespace path (`NS`, `Outer.Inner`) on a sidecar `namespacePrefix`
1616
+ * field — WITHOUT touching `qualifiedName`.
1617
+ *
1618
+ * Some scope-extractors qualify a nested type by its enclosing CLASS chain
1619
+ * (`A.Inner`) but drop the enclosing NAMESPACE, while the structure phase keys
1620
+ * the graph node by the full path (`NS.A.Inner`). `resolveDefGraphId` reads this
1621
+ * tag to retry the node lookup with the namespace-prefixed key before the
1622
+ * simple-name fallback, so same-tail nested bases don't collapse across sibling
1623
+ * namespace members (#1982). `qualifiedName` is deliberately left unchanged, so
1624
+ * the `qualifiedName`-keyed resolution index and existing namespace resolution
1625
+ * (brace-init, UDC ranking, two-phase lookup) are untouched.
1626
+ *
1627
+ * Language-agnostic: it acts only on `Namespace`-kind scopes (a namespace-free
1628
+ * language is a no-op) and is opt-in per provider (call after `populateOwners`).
1629
+ * Namespace segments are taken as each namespace def's own tail, so it composes
1630
+ * for nested namespaces regardless of whether the inner namespace's name is
1631
+ * stored simple or already dotted. Skips defs already carrying the prefix.
1632
+ */
1633
+ function tagNamespacePrefixes(parsed, options = {}) {
1634
+ // Whether a def's `qualifiedName` may ALREADY encode its enclosing namespace.
1635
+ // Where it can (C++, C#), a name equal to — or prefixed by — the namespace path
1636
+ // must not be tagged again. Where it cannot, that guard misreads a coincidence:
1637
+ // a Rust `mod a { pub fn a() }` has `qualifiedName === 'a'` purely because the
1638
+ // item and its module share a name, and skipping it leaves the member looking
1639
+ // like it belongs to the PARENT module.
1640
+ const alreadyQualified = options.qualifiedNamesCarryNamespace === undefined
1641
+ ? true
1642
+ : options.qualifiedNamesCarryNamespace;
1643
+ const scopesById = new Map();
1644
+ for (const scope of parsed.scopes)
1645
+ scopesById.set(scope.id, scope);
1646
+ // Enclosing-namespace prefix for a scope: the dotted path of each ancestor
1647
+ // Namespace scope's name, outermost-first (`['Outer','Inner'] → 'Outer.Inner'`).
1648
+ const namespacePrefixOf = (scope) => {
1649
+ const segments = [];
1650
+ let parentId = scope.parent;
1651
+ while (parentId !== null) {
1652
+ const parent = scopesById.get(parentId);
1653
+ if (parent === undefined)
1654
+ break;
1655
+ if (parent.kind === 'Namespace') {
1656
+ const nsDef = parent.ownedDefs.find((d) => d.type === 'Namespace');
1657
+ const nsQ = nsDef?.qualifiedName;
1658
+ if (nsQ !== undefined && nsQ.length > 0) {
1659
+ const dot = nsQ.lastIndexOf('.');
1660
+ segments.unshift(dot === -1 ? nsQ : nsQ.slice(dot + 1));
1661
+ }
1662
+ }
1663
+ parentId = parent.parent;
1664
+ }
1665
+ return segments.join('.');
1666
+ };
1667
+ for (const scope of parsed.scopes) {
1668
+ if (scope.kind === 'Namespace')
1669
+ continue;
1670
+ const prefix = namespacePrefixOf(scope);
1671
+ if (prefix.length === 0)
1672
+ continue;
1673
+ for (const def of scope.ownedDefs) {
1674
+ const q = def.qualifiedName;
1675
+ if (q === undefined || q.length === 0)
1676
+ continue;
1677
+ if (alreadyQualified && (q === prefix || q.startsWith(`${prefix}.`)))
1678
+ continue;
1679
+ def.namespacePrefix = prefix;
1680
+ }
1681
+ }
1682
+ // #1993: also tag defs declared DIRECTLY in a Namespace scope with that
1683
+ // namespace's OWN full path. The loop above only reaches class-nested defs
1684
+ // (`A::Inner`); a deriving class like `NS1::DA` lives in the namespace scope and
1685
+ // is skipped, so it would carry no prefix and a same-tail cross-namespace base
1686
+ // tie (`NS1::A::Inner` vs `NS2::A::Inner`) could not be broken by the deriving
1687
+ // side. Composed identically to the class-nested path (enclosing tails + own
1688
+ // tail) so the two agree; still sidecar-only (`qualifiedName` untouched).
1689
+ for (const scope of parsed.scopes) {
1690
+ if (scope.kind !== 'Namespace')
1691
+ continue;
1692
+ const ownNsDef = scope.ownedDefs.find((d) => d.type === 'Namespace');
1693
+ const ownQ = ownNsDef?.qualifiedName;
1694
+ if (ownQ === undefined || ownQ.length === 0)
1695
+ continue;
1696
+ const ownTail = ownQ.slice(ownQ.lastIndexOf('.') + 1);
1697
+ const parentPrefix = namespacePrefixOf(scope);
1698
+ const fullPrefix = parentPrefix.length > 0 ? `${parentPrefix}.${ownTail}` : ownTail;
1699
+ for (const def of scope.ownedDefs) {
1700
+ if (def.type === 'Namespace')
1701
+ continue;
1702
+ const q = def.qualifiedName;
1703
+ if (q === undefined || q.length === 0)
1704
+ continue;
1705
+ if (alreadyQualified && (q === fullPrefix || q.startsWith(`${fullPrefix}.`)))
1706
+ continue;
1707
+ if (def.namespacePrefix !== undefined)
1708
+ continue;
1709
+ def.namespacePrefix = fullPrefix;
1710
+ }
1711
+ }
1712
+ }
1713
+ /**
1714
+ * Walk a scope chain upward looking for the innermost enclosing
1715
+ * Class scope and return that class's def. Used by per-language
1716
+ * `super` receiver branches to discover the dispatch base.
1717
+ */
1718
+ function findEnclosingClassDef(startScope, scopes) {
1719
+ let currentId = startScope;
1720
+ const visited = new Set();
1721
+ while (currentId !== null) {
1722
+ if (visited.has(currentId))
1723
+ return undefined;
1724
+ visited.add(currentId);
1725
+ const scope = scopes.scopeTree.getScope(currentId);
1726
+ if (scope === undefined)
1727
+ return undefined;
1728
+ if (scope.kind === 'Class') {
1729
+ const cd = scope.ownedDefs.find((d) => isClassLike(d.type));
1730
+ if (cd !== undefined)
1731
+ return cd;
1732
+ }
1733
+ currentId = scope.parent;
1734
+ }
1735
+ return undefined;
1736
+ }
1737
+ /**
1738
+ * Find a free-function def by simple name across all parsed files,
1739
+ * preferring scope-chain-visible bindings (import + finalized scope
1740
+ * bindings) before falling back to a workspace-wide simple-name scan.
1741
+ *
1742
+ * The fallback scan is intentionally loose so per-language compound
1743
+ * resolvers can find a callable target even when the binding chain
1744
+ * doesn't surface it (e.g. cross-package re-exports the finalize
1745
+ * pass missed). Strictly-typed languages may want to disable the
1746
+ * fallback by simply not calling this helper from their compound
1747
+ * resolver.
1748
+ */
1749
+ function findExportedDefByName(name, inScope, scopes, index) {
1750
+ let currentId = inScope;
1751
+ const visited = new Set();
1752
+ while (currentId !== null) {
1753
+ if (visited.has(currentId))
1754
+ break;
1755
+ visited.add(currentId);
1756
+ const scope = scopes.scopeTree.getScope(currentId);
1757
+ if (scope === undefined)
1758
+ break;
1759
+ // `Object` scopes are a hoist boundary only (#2545/#2551).
1760
+ if (scope.kind !== 'Object') {
1761
+ const local = scope.bindings.get(name);
1762
+ if (local !== undefined) {
1763
+ for (const b of local) {
1764
+ if (b.def.type === 'Function' || b.def.type === 'Method')
1765
+ return b.def;
1766
+ }
1767
+ }
1768
+ const finalized = lookupBindingsAt(currentId, name, scopes);
1769
+ for (const b of finalized) {
1770
+ if (b.def.type === 'Function' || b.def.type === 'Method')
1771
+ return b.def;
1772
+ }
1773
+ }
1774
+ currentId = scope.parent;
1775
+ }
1776
+ // Workspace-wide fallback: the first locally-declared callable binding
1777
+ // matching `name` across every file's Module scope (first-seen-by-file wins;
1778
+ // `origin === 'local'`, callable types Function/Method/Constructor). This is
1779
+ // precomputed ONCE into `index.exportedCallableByName` — byte-identical to the
1780
+ // old per-call scan over `moduleScopeByFile`, but O(1) and disk-read-free
1781
+ // (the old scan faulted every module scope in from disk under the out-of-core scope index). We use
1782
+ // this scope-derived index rather than `SemanticModel.symbols.lookupCallableByName`
1783
+ // because the `origin === 'local'` module-export-visibility filter is a scope
1784
+ // concept the raw symbol index doesn't express.
1785
+ return index.exportedCallableByName.get(name);
1786
+ }
1787
+ /**
1788
+ * Find a member of a class by simple name — delegates to
1789
+ * `SemanticModel.methods` (methods / functions / constructors) with a
1790
+ * fallback to `SemanticModel.fields` (properties / fields /
1791
+ * variables). After `runScopeResolution`'s reconciliation pass
1792
+ * populates both registries from `parsed.localDefs[i].ownerId`
1793
+ * (post-`populateOwners`), this is the single authoritative view of
1794
+ * class membership — no parallel scope-resolution index needed.
1795
+ *
1796
+ * Returns the first-seen overload for methods without arity or
1797
+ * return-type narrowing. Callers that need arity-aware dispatch use
1798
+ * `lookupMethodByOwner(owner, name, argCount)` directly.
1799
+ */
1800
+ function findOwnedMember(ownerDefId, memberName, model) {
1801
+ const method = model.methods.lookupAllByOwner(ownerDefId, memberName)[0];
1802
+ if (method !== undefined)
1803
+ return method;
1804
+ return model.fields.lookupFieldByOwner(ownerDefId, memberName);
1805
+ }
1806
+ /**
1807
+ * Find a file-level def (top-of-module class / function / variable)
1808
+ * by simple name — consults the target file's Module scope's
1809
+ * finalized bindings. Only defs bound at module-scope with
1810
+ * `origin === 'local'` qualify, matching the historical
1811
+ * "module-export-visible" semantics. Class methods and class-body
1812
+ * fields bind at their containing class scope and are naturally
1813
+ * excluded.
1814
+ *
1815
+ * Reads from `WorkspaceResolutionIndex.moduleScopeByFile` (scope-tied
1816
+ * lookup that doesn't live on `SemanticModel`). This intentionally
1817
+ * does NOT call `lookupBindingsAt`: `findExportedDef` answers "what
1818
+ * did the target file declare locally at module scope?", while
1819
+ * `bindingAugmentations` models importer-side visibility created by
1820
+ * post-finalize hooks. Callers that need importer-visible exports use
1821
+ * `findExportedDefByName`, which is dual-channel aware.
1822
+ */
1823
+ function findExportedDef(targetFile, memberName, index) {
1824
+ const moduleScope = index.moduleScopeByFile.get(targetFile);
1825
+ if (moduleScope === undefined)
1826
+ return undefined;
1827
+ const refs = moduleScope.bindings.get(memberName);
1828
+ if (refs === undefined)
1829
+ return undefined;
1830
+ for (const ref of refs) {
1831
+ if (ref.origin === 'local')
1832
+ return ref.def;
1833
+ }
1834
+ return undefined;
1835
+ }