homegraph 0.9.9

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 (549) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +709 -0
  3. package/dist/bin/codegraph.d.ts +26 -0
  4. package/dist/bin/codegraph.d.ts.map +1 -0
  5. package/dist/bin/codegraph.js +1572 -0
  6. package/dist/bin/codegraph.js.map +1 -0
  7. package/dist/bin/homegraph.d.ts +26 -0
  8. package/dist/bin/homegraph.d.ts.map +1 -0
  9. package/dist/bin/homegraph.js +1572 -0
  10. package/dist/bin/homegraph.js.map +1 -0
  11. package/dist/bin/node-version-check.d.ts +37 -0
  12. package/dist/bin/node-version-check.d.ts.map +1 -0
  13. package/dist/bin/node-version-check.js +79 -0
  14. package/dist/bin/node-version-check.js.map +1 -0
  15. package/dist/bin/uninstall.d.ts +14 -0
  16. package/dist/bin/uninstall.d.ts.map +1 -0
  17. package/dist/bin/uninstall.js +36 -0
  18. package/dist/bin/uninstall.js.map +1 -0
  19. package/dist/context/formatter.d.ts +30 -0
  20. package/dist/context/formatter.d.ts.map +1 -0
  21. package/dist/context/formatter.js +263 -0
  22. package/dist/context/formatter.js.map +1 -0
  23. package/dist/context/index.d.ts +119 -0
  24. package/dist/context/index.d.ts.map +1 -0
  25. package/dist/context/index.js +1289 -0
  26. package/dist/context/index.js.map +1 -0
  27. package/dist/context/markers.d.ts +19 -0
  28. package/dist/context/markers.d.ts.map +1 -0
  29. package/dist/context/markers.js +22 -0
  30. package/dist/context/markers.js.map +1 -0
  31. package/dist/db/index.d.ts +101 -0
  32. package/dist/db/index.d.ts.map +1 -0
  33. package/dist/db/index.js +250 -0
  34. package/dist/db/index.js.map +1 -0
  35. package/dist/db/migrations.d.ts +44 -0
  36. package/dist/db/migrations.d.ts.map +1 -0
  37. package/dist/db/migrations.js +131 -0
  38. package/dist/db/migrations.js.map +1 -0
  39. package/dist/db/queries.d.ts +386 -0
  40. package/dist/db/queries.d.ts.map +1 -0
  41. package/dist/db/queries.js +1562 -0
  42. package/dist/db/queries.js.map +1 -0
  43. package/dist/db/schema.sql +151 -0
  44. package/dist/db/sqlite-adapter.d.ts +53 -0
  45. package/dist/db/sqlite-adapter.d.ts.map +1 -0
  46. package/dist/db/sqlite-adapter.js +117 -0
  47. package/dist/db/sqlite-adapter.js.map +1 -0
  48. package/dist/directory.d.ts +57 -0
  49. package/dist/directory.d.ts.map +1 -0
  50. package/dist/directory.js +253 -0
  51. package/dist/directory.js.map +1 -0
  52. package/dist/errors.d.ts +136 -0
  53. package/dist/errors.d.ts.map +1 -0
  54. package/dist/errors.js +219 -0
  55. package/dist/errors.js.map +1 -0
  56. package/dist/extraction/arkanalyzer-extractor.d.ts +6 -0
  57. package/dist/extraction/arkanalyzer-extractor.d.ts.map +1 -0
  58. package/dist/extraction/arkanalyzer-extractor.js +11 -0
  59. package/dist/extraction/arkanalyzer-extractor.js.map +1 -0
  60. package/dist/extraction/arkanalyzer-project.d.ts +20 -0
  61. package/dist/extraction/arkanalyzer-project.d.ts.map +1 -0
  62. package/dist/extraction/arkanalyzer-project.js +596 -0
  63. package/dist/extraction/arkanalyzer-project.js.map +1 -0
  64. package/dist/extraction/context.d.ts +12 -0
  65. package/dist/extraction/context.d.ts.map +1 -0
  66. package/dist/extraction/context.js +29 -0
  67. package/dist/extraction/context.js.map +1 -0
  68. package/dist/extraction/dfm-extractor.d.ts +31 -0
  69. package/dist/extraction/dfm-extractor.d.ts.map +1 -0
  70. package/dist/extraction/dfm-extractor.js +151 -0
  71. package/dist/extraction/dfm-extractor.js.map +1 -0
  72. package/dist/extraction/extraction-version.d.ts +25 -0
  73. package/dist/extraction/extraction-version.d.ts.map +1 -0
  74. package/dist/extraction/extraction-version.js +28 -0
  75. package/dist/extraction/extraction-version.js.map +1 -0
  76. package/dist/extraction/generated-detection.d.ts +30 -0
  77. package/dist/extraction/generated-detection.d.ts.map +1 -0
  78. package/dist/extraction/generated-detection.js +80 -0
  79. package/dist/extraction/generated-detection.js.map +1 -0
  80. package/dist/extraction/grammars.d.ts +108 -0
  81. package/dist/extraction/grammars.d.ts.map +1 -0
  82. package/dist/extraction/grammars.js +465 -0
  83. package/dist/extraction/grammars.js.map +1 -0
  84. package/dist/extraction/index.d.ts +138 -0
  85. package/dist/extraction/index.d.ts.map +1 -0
  86. package/dist/extraction/index.js +1396 -0
  87. package/dist/extraction/index.js.map +1 -0
  88. package/dist/extraction/languages/arkts.d.ts +18 -0
  89. package/dist/extraction/languages/arkts.d.ts.map +1 -0
  90. package/dist/extraction/languages/arkts.js +878 -0
  91. package/dist/extraction/languages/arkts.js.map +1 -0
  92. package/dist/extraction/languages/c-cpp.d.ts +4 -0
  93. package/dist/extraction/languages/c-cpp.d.ts.map +1 -0
  94. package/dist/extraction/languages/c-cpp.js +173 -0
  95. package/dist/extraction/languages/c-cpp.js.map +1 -0
  96. package/dist/extraction/languages/csharp.d.ts +25 -0
  97. package/dist/extraction/languages/csharp.d.ts.map +1 -0
  98. package/dist/extraction/languages/csharp.js +120 -0
  99. package/dist/extraction/languages/csharp.js.map +1 -0
  100. package/dist/extraction/languages/dart.d.ts +3 -0
  101. package/dist/extraction/languages/dart.d.ts.map +1 -0
  102. package/dist/extraction/languages/dart.js +192 -0
  103. package/dist/extraction/languages/dart.js.map +1 -0
  104. package/dist/extraction/languages/go.d.ts +3 -0
  105. package/dist/extraction/languages/go.d.ts.map +1 -0
  106. package/dist/extraction/languages/go.js +74 -0
  107. package/dist/extraction/languages/go.js.map +1 -0
  108. package/dist/extraction/languages/index.d.ts +10 -0
  109. package/dist/extraction/languages/index.d.ts.map +1 -0
  110. package/dist/extraction/languages/index.js +51 -0
  111. package/dist/extraction/languages/index.js.map +1 -0
  112. package/dist/extraction/languages/java.d.ts +3 -0
  113. package/dist/extraction/languages/java.d.ts.map +1 -0
  114. package/dist/extraction/languages/java.js +74 -0
  115. package/dist/extraction/languages/java.js.map +1 -0
  116. package/dist/extraction/languages/javascript.d.ts +3 -0
  117. package/dist/extraction/languages/javascript.d.ts.map +1 -0
  118. package/dist/extraction/languages/javascript.js +90 -0
  119. package/dist/extraction/languages/javascript.js.map +1 -0
  120. package/dist/extraction/languages/kotlin.d.ts +3 -0
  121. package/dist/extraction/languages/kotlin.d.ts.map +1 -0
  122. package/dist/extraction/languages/kotlin.js +285 -0
  123. package/dist/extraction/languages/kotlin.js.map +1 -0
  124. package/dist/extraction/languages/lua.d.ts +3 -0
  125. package/dist/extraction/languages/lua.d.ts.map +1 -0
  126. package/dist/extraction/languages/lua.js +150 -0
  127. package/dist/extraction/languages/lua.js.map +1 -0
  128. package/dist/extraction/languages/luau.d.ts +3 -0
  129. package/dist/extraction/languages/luau.d.ts.map +1 -0
  130. package/dist/extraction/languages/luau.js +37 -0
  131. package/dist/extraction/languages/luau.js.map +1 -0
  132. package/dist/extraction/languages/objc.d.ts +3 -0
  133. package/dist/extraction/languages/objc.d.ts.map +1 -0
  134. package/dist/extraction/languages/objc.js +133 -0
  135. package/dist/extraction/languages/objc.js.map +1 -0
  136. package/dist/extraction/languages/pascal.d.ts +3 -0
  137. package/dist/extraction/languages/pascal.d.ts.map +1 -0
  138. package/dist/extraction/languages/pascal.js +66 -0
  139. package/dist/extraction/languages/pascal.js.map +1 -0
  140. package/dist/extraction/languages/php.d.ts +3 -0
  141. package/dist/extraction/languages/php.d.ts.map +1 -0
  142. package/dist/extraction/languages/php.js +120 -0
  143. package/dist/extraction/languages/php.js.map +1 -0
  144. package/dist/extraction/languages/python.d.ts +3 -0
  145. package/dist/extraction/languages/python.d.ts.map +1 -0
  146. package/dist/extraction/languages/python.js +56 -0
  147. package/dist/extraction/languages/python.js.map +1 -0
  148. package/dist/extraction/languages/ruby.d.ts +3 -0
  149. package/dist/extraction/languages/ruby.d.ts.map +1 -0
  150. package/dist/extraction/languages/ruby.js +149 -0
  151. package/dist/extraction/languages/ruby.js.map +1 -0
  152. package/dist/extraction/languages/rust.d.ts +3 -0
  153. package/dist/extraction/languages/rust.d.ts.map +1 -0
  154. package/dist/extraction/languages/rust.js +113 -0
  155. package/dist/extraction/languages/rust.js.map +1 -0
  156. package/dist/extraction/languages/scala.d.ts +3 -0
  157. package/dist/extraction/languages/scala.d.ts.map +1 -0
  158. package/dist/extraction/languages/scala.js +174 -0
  159. package/dist/extraction/languages/scala.js.map +1 -0
  160. package/dist/extraction/languages/swift.d.ts +3 -0
  161. package/dist/extraction/languages/swift.d.ts.map +1 -0
  162. package/dist/extraction/languages/swift.js +91 -0
  163. package/dist/extraction/languages/swift.js.map +1 -0
  164. package/dist/extraction/languages/typescript.d.ts +3 -0
  165. package/dist/extraction/languages/typescript.d.ts.map +1 -0
  166. package/dist/extraction/languages/typescript.js +129 -0
  167. package/dist/extraction/languages/typescript.js.map +1 -0
  168. package/dist/extraction/liquid-extractor.d.ts +59 -0
  169. package/dist/extraction/liquid-extractor.d.ts.map +1 -0
  170. package/dist/extraction/liquid-extractor.js +354 -0
  171. package/dist/extraction/liquid-extractor.js.map +1 -0
  172. package/dist/extraction/mybatis-extractor.d.ts +48 -0
  173. package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  174. package/dist/extraction/mybatis-extractor.js +198 -0
  175. package/dist/extraction/mybatis-extractor.js.map +1 -0
  176. package/dist/extraction/parse-worker.d.ts +8 -0
  177. package/dist/extraction/parse-worker.d.ts.map +1 -0
  178. package/dist/extraction/parse-worker.js +94 -0
  179. package/dist/extraction/parse-worker.js.map +1 -0
  180. package/dist/extraction/razor-extractor.d.ts +42 -0
  181. package/dist/extraction/razor-extractor.d.ts.map +1 -0
  182. package/dist/extraction/razor-extractor.js +285 -0
  183. package/dist/extraction/razor-extractor.js.map +1 -0
  184. package/dist/extraction/svelte-extractor.d.ts +56 -0
  185. package/dist/extraction/svelte-extractor.d.ts.map +1 -0
  186. package/dist/extraction/svelte-extractor.js +272 -0
  187. package/dist/extraction/svelte-extractor.js.map +1 -0
  188. package/dist/extraction/tree-sitter-helpers.d.ts +28 -0
  189. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
  190. package/dist/extraction/tree-sitter-helpers.js +103 -0
  191. package/dist/extraction/tree-sitter-helpers.js.map +1 -0
  192. package/dist/extraction/tree-sitter-types.d.ts +210 -0
  193. package/dist/extraction/tree-sitter-types.d.ts.map +1 -0
  194. package/dist/extraction/tree-sitter-types.js +10 -0
  195. package/dist/extraction/tree-sitter-types.js.map +1 -0
  196. package/dist/extraction/tree-sitter.d.ts +455 -0
  197. package/dist/extraction/tree-sitter.d.ts.map +1 -0
  198. package/dist/extraction/tree-sitter.js +4089 -0
  199. package/dist/extraction/tree-sitter.js.map +1 -0
  200. package/dist/extraction/vue-extractor.d.ts +51 -0
  201. package/dist/extraction/vue-extractor.d.ts.map +1 -0
  202. package/dist/extraction/vue-extractor.js +251 -0
  203. package/dist/extraction/vue-extractor.js.map +1 -0
  204. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  205. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  206. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  207. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  208. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  209. package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
  210. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  211. package/dist/extraction/wasm-runtime-flags.js +106 -0
  212. package/dist/extraction/wasm-runtime-flags.js.map +1 -0
  213. package/dist/graph/index.d.ts +8 -0
  214. package/dist/graph/index.d.ts.map +1 -0
  215. package/dist/graph/index.js +13 -0
  216. package/dist/graph/index.js.map +1 -0
  217. package/dist/graph/queries.d.ts +106 -0
  218. package/dist/graph/queries.d.ts.map +1 -0
  219. package/dist/graph/queries.js +339 -0
  220. package/dist/graph/queries.js.map +1 -0
  221. package/dist/graph/traversal.d.ts +127 -0
  222. package/dist/graph/traversal.d.ts.map +1 -0
  223. package/dist/graph/traversal.js +531 -0
  224. package/dist/graph/traversal.js.map +1 -0
  225. package/dist/index.d.ts +522 -0
  226. package/dist/index.d.ts.map +1 -0
  227. package/dist/index.js +947 -0
  228. package/dist/index.js.map +1 -0
  229. package/dist/installer/config-writer.d.ts +28 -0
  230. package/dist/installer/config-writer.d.ts.map +1 -0
  231. package/dist/installer/config-writer.js +91 -0
  232. package/dist/installer/config-writer.js.map +1 -0
  233. package/dist/installer/index.d.ts +100 -0
  234. package/dist/installer/index.d.ts.map +1 -0
  235. package/dist/installer/index.js +497 -0
  236. package/dist/installer/index.js.map +1 -0
  237. package/dist/installer/instructions-template.d.ts +18 -0
  238. package/dist/installer/instructions-template.d.ts.map +1 -0
  239. package/dist/installer/instructions-template.js +21 -0
  240. package/dist/installer/instructions-template.js.map +1 -0
  241. package/dist/installer/targets/antigravity.d.ts +57 -0
  242. package/dist/installer/targets/antigravity.d.ts.map +1 -0
  243. package/dist/installer/targets/antigravity.js +308 -0
  244. package/dist/installer/targets/antigravity.js.map +1 -0
  245. package/dist/installer/targets/claude.d.ts +56 -0
  246. package/dist/installer/targets/claude.d.ts.map +1 -0
  247. package/dist/installer/targets/claude.js +388 -0
  248. package/dist/installer/targets/claude.js.map +1 -0
  249. package/dist/installer/targets/codex.d.ts +18 -0
  250. package/dist/installer/targets/codex.d.ts.map +1 -0
  251. package/dist/installer/targets/codex.js +187 -0
  252. package/dist/installer/targets/codex.js.map +1 -0
  253. package/dist/installer/targets/cursor.d.ts +35 -0
  254. package/dist/installer/targets/cursor.d.ts.map +1 -0
  255. package/dist/installer/targets/cursor.js +254 -0
  256. package/dist/installer/targets/cursor.js.map +1 -0
  257. package/dist/installer/targets/gemini.d.ts +26 -0
  258. package/dist/installer/targets/gemini.d.ts.map +1 -0
  259. package/dist/installer/targets/gemini.js +167 -0
  260. package/dist/installer/targets/gemini.js.map +1 -0
  261. package/dist/installer/targets/hermes.d.ts +18 -0
  262. package/dist/installer/targets/hermes.d.ts.map +1 -0
  263. package/dist/installer/targets/hermes.js +359 -0
  264. package/dist/installer/targets/hermes.js.map +1 -0
  265. package/dist/installer/targets/kiro.d.ts +27 -0
  266. package/dist/installer/targets/kiro.d.ts.map +1 -0
  267. package/dist/installer/targets/kiro.js +178 -0
  268. package/dist/installer/targets/kiro.js.map +1 -0
  269. package/dist/installer/targets/opencode.d.ts +30 -0
  270. package/dist/installer/targets/opencode.d.ts.map +1 -0
  271. package/dist/installer/targets/opencode.js +237 -0
  272. package/dist/installer/targets/opencode.js.map +1 -0
  273. package/dist/installer/targets/registry.d.ts +35 -0
  274. package/dist/installer/targets/registry.d.ts.map +1 -0
  275. package/dist/installer/targets/registry.js +91 -0
  276. package/dist/installer/targets/registry.js.map +1 -0
  277. package/dist/installer/targets/shared.d.ts +77 -0
  278. package/dist/installer/targets/shared.d.ts.map +1 -0
  279. package/dist/installer/targets/shared.js +247 -0
  280. package/dist/installer/targets/shared.js.map +1 -0
  281. package/dist/installer/targets/toml.d.ts +52 -0
  282. package/dist/installer/targets/toml.d.ts.map +1 -0
  283. package/dist/installer/targets/toml.js +147 -0
  284. package/dist/installer/targets/toml.js.map +1 -0
  285. package/dist/installer/targets/types.d.ts +101 -0
  286. package/dist/installer/targets/types.d.ts.map +1 -0
  287. package/dist/installer/targets/types.js +16 -0
  288. package/dist/installer/targets/types.js.map +1 -0
  289. package/dist/mcp/daemon-paths.d.ts +46 -0
  290. package/dist/mcp/daemon-paths.d.ts.map +1 -0
  291. package/dist/mcp/daemon-paths.js +125 -0
  292. package/dist/mcp/daemon-paths.js.map +1 -0
  293. package/dist/mcp/daemon.d.ts +220 -0
  294. package/dist/mcp/daemon.d.ts.map +1 -0
  295. package/dist/mcp/daemon.js +616 -0
  296. package/dist/mcp/daemon.js.map +1 -0
  297. package/dist/mcp/engine.d.ts +105 -0
  298. package/dist/mcp/engine.d.ts.map +1 -0
  299. package/dist/mcp/engine.js +270 -0
  300. package/dist/mcp/engine.js.map +1 -0
  301. package/dist/mcp/index.d.ts +112 -0
  302. package/dist/mcp/index.d.ts.map +1 -0
  303. package/dist/mcp/index.js +478 -0
  304. package/dist/mcp/index.js.map +1 -0
  305. package/dist/mcp/ppid-watchdog.d.ts +44 -0
  306. package/dist/mcp/ppid-watchdog.d.ts.map +1 -0
  307. package/dist/mcp/ppid-watchdog.js +27 -0
  308. package/dist/mcp/ppid-watchdog.js.map +1 -0
  309. package/dist/mcp/proxy.d.ts +81 -0
  310. package/dist/mcp/proxy.d.ts.map +1 -0
  311. package/dist/mcp/proxy.js +584 -0
  312. package/dist/mcp/proxy.js.map +1 -0
  313. package/dist/mcp/server-instructions.d.ts +19 -0
  314. package/dist/mcp/server-instructions.d.ts.map +1 -0
  315. package/dist/mcp/server-instructions.js +74 -0
  316. package/dist/mcp/server-instructions.js.map +1 -0
  317. package/dist/mcp/session.d.ts +77 -0
  318. package/dist/mcp/session.d.ts.map +1 -0
  319. package/dist/mcp/session.js +294 -0
  320. package/dist/mcp/session.js.map +1 -0
  321. package/dist/mcp/tools.d.ts +413 -0
  322. package/dist/mcp/tools.d.ts.map +1 -0
  323. package/dist/mcp/tools.js +3049 -0
  324. package/dist/mcp/tools.js.map +1 -0
  325. package/dist/mcp/transport.d.ts +188 -0
  326. package/dist/mcp/transport.d.ts.map +1 -0
  327. package/dist/mcp/transport.js +343 -0
  328. package/dist/mcp/transport.js.map +1 -0
  329. package/dist/mcp/version.d.ts +19 -0
  330. package/dist/mcp/version.d.ts.map +1 -0
  331. package/dist/mcp/version.js +71 -0
  332. package/dist/mcp/version.js.map +1 -0
  333. package/dist/resolution/callback-synthesizer.d.ts +10 -0
  334. package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  335. package/dist/resolution/callback-synthesizer.js +1818 -0
  336. package/dist/resolution/callback-synthesizer.js.map +1 -0
  337. package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
  338. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  339. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  340. package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  341. package/dist/resolution/frameworks/csharp.d.ts +8 -0
  342. package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
  343. package/dist/resolution/frameworks/csharp.js +241 -0
  344. package/dist/resolution/frameworks/csharp.js.map +1 -0
  345. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  346. package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  347. package/dist/resolution/frameworks/drupal.js +367 -0
  348. package/dist/resolution/frameworks/drupal.js.map +1 -0
  349. package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  350. package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  351. package/dist/resolution/frameworks/expo-modules.js +148 -0
  352. package/dist/resolution/frameworks/expo-modules.js.map +1 -0
  353. package/dist/resolution/frameworks/express.d.ts +8 -0
  354. package/dist/resolution/frameworks/express.d.ts.map +1 -0
  355. package/dist/resolution/frameworks/express.js +308 -0
  356. package/dist/resolution/frameworks/express.js.map +1 -0
  357. package/dist/resolution/frameworks/fabric.d.ts +3 -0
  358. package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  359. package/dist/resolution/frameworks/fabric.js +354 -0
  360. package/dist/resolution/frameworks/fabric.js.map +1 -0
  361. package/dist/resolution/frameworks/go.d.ts +8 -0
  362. package/dist/resolution/frameworks/go.d.ts.map +1 -0
  363. package/dist/resolution/frameworks/go.js +161 -0
  364. package/dist/resolution/frameworks/go.js.map +1 -0
  365. package/dist/resolution/frameworks/index.d.ts +48 -0
  366. package/dist/resolution/frameworks/index.d.ts.map +1 -0
  367. package/dist/resolution/frameworks/index.js +161 -0
  368. package/dist/resolution/frameworks/index.js.map +1 -0
  369. package/dist/resolution/frameworks/java.d.ts +8 -0
  370. package/dist/resolution/frameworks/java.d.ts.map +1 -0
  371. package/dist/resolution/frameworks/java.js +504 -0
  372. package/dist/resolution/frameworks/java.js.map +1 -0
  373. package/dist/resolution/frameworks/laravel.d.ts +13 -0
  374. package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
  375. package/dist/resolution/frameworks/laravel.js +257 -0
  376. package/dist/resolution/frameworks/laravel.js.map +1 -0
  377. package/dist/resolution/frameworks/nestjs.d.ts +26 -0
  378. package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
  379. package/dist/resolution/frameworks/nestjs.js +698 -0
  380. package/dist/resolution/frameworks/nestjs.js.map +1 -0
  381. package/dist/resolution/frameworks/play.d.ts +19 -0
  382. package/dist/resolution/frameworks/play.d.ts.map +1 -0
  383. package/dist/resolution/frameworks/play.js +111 -0
  384. package/dist/resolution/frameworks/play.js.map +1 -0
  385. package/dist/resolution/frameworks/python.d.ts +10 -0
  386. package/dist/resolution/frameworks/python.d.ts.map +1 -0
  387. package/dist/resolution/frameworks/python.js +400 -0
  388. package/dist/resolution/frameworks/python.js.map +1 -0
  389. package/dist/resolution/frameworks/react-native.d.ts +3 -0
  390. package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  391. package/dist/resolution/frameworks/react-native.js +410 -0
  392. package/dist/resolution/frameworks/react-native.js.map +1 -0
  393. package/dist/resolution/frameworks/react.d.ts +8 -0
  394. package/dist/resolution/frameworks/react.d.ts.map +1 -0
  395. package/dist/resolution/frameworks/react.js +365 -0
  396. package/dist/resolution/frameworks/react.js.map +1 -0
  397. package/dist/resolution/frameworks/ruby.d.ts +8 -0
  398. package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
  399. package/dist/resolution/frameworks/ruby.js +302 -0
  400. package/dist/resolution/frameworks/ruby.js.map +1 -0
  401. package/dist/resolution/frameworks/rust.d.ts +8 -0
  402. package/dist/resolution/frameworks/rust.d.ts.map +1 -0
  403. package/dist/resolution/frameworks/rust.js +304 -0
  404. package/dist/resolution/frameworks/rust.js.map +1 -0
  405. package/dist/resolution/frameworks/svelte.d.ts +9 -0
  406. package/dist/resolution/frameworks/svelte.d.ts.map +1 -0
  407. package/dist/resolution/frameworks/svelte.js +249 -0
  408. package/dist/resolution/frameworks/svelte.js.map +1 -0
  409. package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  410. package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  411. package/dist/resolution/frameworks/swift-objc.js +252 -0
  412. package/dist/resolution/frameworks/swift-objc.js.map +1 -0
  413. package/dist/resolution/frameworks/swift.d.ts +10 -0
  414. package/dist/resolution/frameworks/swift.d.ts.map +1 -0
  415. package/dist/resolution/frameworks/swift.js +400 -0
  416. package/dist/resolution/frameworks/swift.js.map +1 -0
  417. package/dist/resolution/frameworks/vue.d.ts +9 -0
  418. package/dist/resolution/frameworks/vue.d.ts.map +1 -0
  419. package/dist/resolution/frameworks/vue.js +306 -0
  420. package/dist/resolution/frameworks/vue.js.map +1 -0
  421. package/dist/resolution/go-module.d.ts +26 -0
  422. package/dist/resolution/go-module.d.ts.map +1 -0
  423. package/dist/resolution/go-module.js +78 -0
  424. package/dist/resolution/go-module.js.map +1 -0
  425. package/dist/resolution/import-resolver.d.ts +68 -0
  426. package/dist/resolution/import-resolver.d.ts.map +1 -0
  427. package/dist/resolution/import-resolver.js +1726 -0
  428. package/dist/resolution/import-resolver.js.map +1 -0
  429. package/dist/resolution/index.d.ts +159 -0
  430. package/dist/resolution/index.d.ts.map +1 -0
  431. package/dist/resolution/index.js +1025 -0
  432. package/dist/resolution/index.js.map +1 -0
  433. package/dist/resolution/lru-cache.d.ts +24 -0
  434. package/dist/resolution/lru-cache.d.ts.map +1 -0
  435. package/dist/resolution/lru-cache.js +62 -0
  436. package/dist/resolution/lru-cache.js.map +1 -0
  437. package/dist/resolution/name-matcher.d.ts +52 -0
  438. package/dist/resolution/name-matcher.d.ts.map +1 -0
  439. package/dist/resolution/name-matcher.js +707 -0
  440. package/dist/resolution/name-matcher.js.map +1 -0
  441. package/dist/resolution/path-aliases.d.ts +68 -0
  442. package/dist/resolution/path-aliases.d.ts.map +1 -0
  443. package/dist/resolution/path-aliases.js +238 -0
  444. package/dist/resolution/path-aliases.js.map +1 -0
  445. package/dist/resolution/strip-comments.d.ts +27 -0
  446. package/dist/resolution/strip-comments.d.ts.map +1 -0
  447. package/dist/resolution/strip-comments.js +441 -0
  448. package/dist/resolution/strip-comments.js.map +1 -0
  449. package/dist/resolution/swift-objc-bridge.d.ts +134 -0
  450. package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  451. package/dist/resolution/swift-objc-bridge.js +256 -0
  452. package/dist/resolution/swift-objc-bridge.js.map +1 -0
  453. package/dist/resolution/types.d.ts +216 -0
  454. package/dist/resolution/types.d.ts.map +1 -0
  455. package/dist/resolution/types.js +8 -0
  456. package/dist/resolution/types.js.map +1 -0
  457. package/dist/resolution/workspace-packages.d.ts +48 -0
  458. package/dist/resolution/workspace-packages.d.ts.map +1 -0
  459. package/dist/resolution/workspace-packages.js +208 -0
  460. package/dist/resolution/workspace-packages.js.map +1 -0
  461. package/dist/search/query-parser.d.ts +57 -0
  462. package/dist/search/query-parser.d.ts.map +1 -0
  463. package/dist/search/query-parser.js +177 -0
  464. package/dist/search/query-parser.js.map +1 -0
  465. package/dist/search/query-utils.d.ts +71 -0
  466. package/dist/search/query-utils.d.ts.map +1 -0
  467. package/dist/search/query-utils.js +380 -0
  468. package/dist/search/query-utils.js.map +1 -0
  469. package/dist/sync/git-hooks.d.ts +45 -0
  470. package/dist/sync/git-hooks.d.ts.map +1 -0
  471. package/dist/sync/git-hooks.js +225 -0
  472. package/dist/sync/git-hooks.js.map +1 -0
  473. package/dist/sync/index.d.ts +19 -0
  474. package/dist/sync/index.d.ts.map +1 -0
  475. package/dist/sync/index.js +35 -0
  476. package/dist/sync/index.js.map +1 -0
  477. package/dist/sync/watch-policy.d.ts +48 -0
  478. package/dist/sync/watch-policy.d.ts.map +1 -0
  479. package/dist/sync/watch-policy.js +124 -0
  480. package/dist/sync/watch-policy.js.map +1 -0
  481. package/dist/sync/watcher.d.ts +283 -0
  482. package/dist/sync/watcher.d.ts.map +1 -0
  483. package/dist/sync/watcher.js +606 -0
  484. package/dist/sync/watcher.js.map +1 -0
  485. package/dist/sync/worktree.d.ts +54 -0
  486. package/dist/sync/worktree.d.ts.map +1 -0
  487. package/dist/sync/worktree.js +137 -0
  488. package/dist/sync/worktree.js.map +1 -0
  489. package/dist/types.d.ts +377 -0
  490. package/dist/types.d.ts.map +1 -0
  491. package/dist/types.js +80 -0
  492. package/dist/types.js.map +1 -0
  493. package/dist/ui/glyphs.d.ts +42 -0
  494. package/dist/ui/glyphs.d.ts.map +1 -0
  495. package/dist/ui/glyphs.js +78 -0
  496. package/dist/ui/glyphs.js.map +1 -0
  497. package/dist/ui/shimmer-progress.d.ts +11 -0
  498. package/dist/ui/shimmer-progress.d.ts.map +1 -0
  499. package/dist/ui/shimmer-progress.js +90 -0
  500. package/dist/ui/shimmer-progress.js.map +1 -0
  501. package/dist/ui/shimmer-worker.d.ts +2 -0
  502. package/dist/ui/shimmer-worker.d.ts.map +1 -0
  503. package/dist/ui/shimmer-worker.js +118 -0
  504. package/dist/ui/shimmer-worker.js.map +1 -0
  505. package/dist/ui/types.d.ts +17 -0
  506. package/dist/ui/types.d.ts.map +1 -0
  507. package/dist/ui/types.js +3 -0
  508. package/dist/ui/types.js.map +1 -0
  509. package/dist/upgrade/index.d.ts +132 -0
  510. package/dist/upgrade/index.d.ts.map +1 -0
  511. package/dist/upgrade/index.js +462 -0
  512. package/dist/upgrade/index.js.map +1 -0
  513. package/dist/utils.d.ts +205 -0
  514. package/dist/utils.d.ts.map +1 -0
  515. package/dist/utils.js +549 -0
  516. package/dist/utils.js.map +1 -0
  517. package/package.json +57 -0
  518. package/scripts/add-lang/bench.sh +60 -0
  519. package/scripts/add-lang/check-grammar.mjs +75 -0
  520. package/scripts/add-lang/dump-ast.mjs +103 -0
  521. package/scripts/add-lang/verify-extraction.mjs +70 -0
  522. package/scripts/agent-eval/arms-F.sh +21 -0
  523. package/scripts/agent-eval/arms-matrix.sh +37 -0
  524. package/scripts/agent-eval/audit.sh +68 -0
  525. package/scripts/agent-eval/bench-readme.sh +28 -0
  526. package/scripts/agent-eval/bench-why-repo.sh +22 -0
  527. package/scripts/agent-eval/block-read-hook.sh +19 -0
  528. package/scripts/agent-eval/hook-settings.json +15 -0
  529. package/scripts/agent-eval/itrun.sh +120 -0
  530. package/scripts/agent-eval/parse-arms.mjs +116 -0
  531. package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
  532. package/scripts/agent-eval/parse-run.mjs +45 -0
  533. package/scripts/agent-eval/parse-session.mjs +93 -0
  534. package/scripts/agent-eval/probe-context.mjs +21 -0
  535. package/scripts/agent-eval/probe-explore.mjs +40 -0
  536. package/scripts/agent-eval/probe-node.mjs +20 -0
  537. package/scripts/agent-eval/probe-sweep.mjs +119 -0
  538. package/scripts/agent-eval/probe-trace.mjs +20 -0
  539. package/scripts/agent-eval/run-agent.sh +34 -0
  540. package/scripts/agent-eval/run-all.sh +67 -0
  541. package/scripts/agent-eval/run-arms.sh +56 -0
  542. package/scripts/agent-eval/seq-matrix.mjs +137 -0
  543. package/scripts/build-bundle.sh +118 -0
  544. package/scripts/extract-release-notes.mjs +130 -0
  545. package/scripts/local-install.sh +41 -0
  546. package/scripts/npm-sdk.js +75 -0
  547. package/scripts/npm-shim.js +246 -0
  548. package/scripts/pack-npm.sh +119 -0
  549. package/scripts/prepare-release.mjs +270 -0
@@ -0,0 +1,1726 @@
1
+ "use strict";
2
+ /**
3
+ * Import Resolver
4
+ *
5
+ * Resolves import paths to actual files and symbols.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.resolveImportPath = resolveImportPath;
42
+ exports.clearCppIncludeDirCache = clearCppIncludeDirCache;
43
+ exports.loadCppIncludeDirs = loadCppIncludeDirs;
44
+ exports.extractImportMappings = extractImportMappings;
45
+ exports.clearImportMappingCache = clearImportMappingCache;
46
+ exports.extractReExports = extractReExports;
47
+ exports.resolveJvmImport = resolveJvmImport;
48
+ exports.resolveViaImport = resolveViaImport;
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const path_aliases_1 = require("./path-aliases");
52
+ const workspace_packages_1 = require("./workspace-packages");
53
+ /**
54
+ * Extension resolution order by language
55
+ */
56
+ const EXTENSION_RESOLUTION = {
57
+ typescript: ['.ts', '.tsx', '.d.ts', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js'],
58
+ javascript: ['.js', '.jsx', '.mjs', '.cjs', '/index.js', '/index.jsx'],
59
+ tsx: ['.tsx', '.ts', '.d.ts', '.js', '.jsx', '/index.tsx', '/index.ts', '/index.js'],
60
+ jsx: ['.jsx', '.js', '/index.jsx', '/index.js'],
61
+ // SFC consumers import plain TS/JS, sibling components, and barrels
62
+ // (`./lib` → `./lib/index.ts`). Without a list, relative imports from a
63
+ // `.svelte`/`.vue` file resolve to nothing, so barrel callers vanish (#629).
64
+ svelte: ['.ts', '.js', '.svelte', '.tsx', '.jsx', '/index.ts', '/index.js', '/index.svelte'],
65
+ vue: ['.ts', '.js', '.vue', '.tsx', '.jsx', '/index.ts', '/index.js', '/index.vue'],
66
+ python: ['.py', '/__init__.py'],
67
+ go: ['.go'],
68
+ rust: ['.rs', '/mod.rs'],
69
+ java: ['.java'],
70
+ c: ['.h', '.c'],
71
+ cpp: ['.h', '.hpp', '.hxx', '.cpp', '.cc', '.cxx'],
72
+ csharp: ['.cs'],
73
+ php: ['.php'],
74
+ ruby: ['.rb'],
75
+ objc: ['.h', '.m', '.mm'],
76
+ };
77
+ /**
78
+ * Resolve an import path to an actual file
79
+ */
80
+ function resolveImportPath(importPath, fromFile, language, context) {
81
+ // Skip external/npm packages — but pass the context so the
82
+ // bare-specifier heuristic can consult the project's tsconfig
83
+ // alias map first (custom prefixes like `@components/*` would
84
+ // otherwise be misclassified as npm).
85
+ if (isExternalImport(importPath, language, context)) {
86
+ return null;
87
+ }
88
+ const projectRoot = context.getProjectRoot();
89
+ const fromDir = path.dirname(path.join(projectRoot, fromFile));
90
+ // Handle relative imports
91
+ if (importPath.startsWith('.')) {
92
+ return resolveRelativeImport(importPath, fromDir, language, context);
93
+ }
94
+ // Handle absolute/aliased imports (like @/ or src/)
95
+ const aliased = resolveAliasedImport(importPath, projectRoot, language, context);
96
+ if (aliased)
97
+ return aliased;
98
+ // C/C++ include directory search: when neither relative nor aliased
99
+ // resolution found a match, search -I directories from
100
+ // compile_commands.json or heuristic probing.
101
+ if (language === 'c' || language === 'cpp') {
102
+ return resolveCppIncludePath(importPath, language, context);
103
+ }
104
+ return null;
105
+ }
106
+ /**
107
+ * C and C++ standard library header names (without delimiters).
108
+ * Used by isExternalImport to filter system includes from resolution.
109
+ */
110
+ const C_CPP_STDLIB_HEADERS = new Set([
111
+ // C standard library headers
112
+ 'assert.h', 'complex.h', 'ctype.h', 'errno.h', 'fenv.h', 'float.h',
113
+ 'inttypes.h', 'iso646.h', 'limits.h', 'locale.h', 'math.h', 'setjmp.h',
114
+ 'signal.h', 'stdalign.h', 'stdarg.h', 'stdatomic.h', 'stdbool.h',
115
+ 'stddef.h', 'stdint.h', 'stdio.h', 'stdlib.h', 'stdnoreturn.h',
116
+ 'string.h', 'tgmath.h', 'threads.h', 'time.h', 'uchar.h', 'wchar.h',
117
+ 'wctype.h',
118
+ // C++ C-library wrappers (cname form)
119
+ 'cassert', 'ccomplex', 'cctype', 'cerrno', 'cfenv', 'cfloat',
120
+ 'cinttypes', 'ciso646', 'climits', 'clocale', 'cmath', 'csetjmp',
121
+ 'csignal', 'cstdalign', 'cstdarg', 'cstdbool', 'cstddef', 'cstdint',
122
+ 'cstdio', 'cstdlib', 'cstring', 'ctgmath', 'ctime', 'cuchar',
123
+ 'cwchar', 'cwctype',
124
+ // C++ STL headers
125
+ 'algorithm', 'any', 'array', 'atomic', 'barrier', 'bit', 'bitset',
126
+ 'charconv', 'chrono', 'codecvt', 'compare', 'complex', 'concepts',
127
+ 'condition_variable', 'coroutine', 'deque', 'exception', 'execution',
128
+ 'expected', 'filesystem', 'format', 'forward_list', 'fstream',
129
+ 'functional', 'future', 'generator', 'initializer_list', 'iomanip',
130
+ 'ios', 'iosfwd', 'iostream', 'istream', 'iterator', 'latch',
131
+ 'limits', 'list', 'locale', 'map', 'mdspan', 'memory', 'memory_resource',
132
+ 'mutex', 'new', 'numbers', 'numeric', 'optional', 'ostream', 'print',
133
+ 'queue', 'random', 'ranges', 'ratio', 'regex', 'scoped_allocator',
134
+ 'semaphore', 'set', 'shared_mutex', 'source_location', 'span',
135
+ 'spanstream', 'sstream', 'stack', 'stacktrace', 'stdexcept',
136
+ 'stdfloat', 'stop_token', 'streambuf', 'string', 'string_view',
137
+ 'strstream', 'syncstream', 'system_error', 'thread', 'tuple',
138
+ 'type_traits', 'typeindex', 'typeinfo', 'unordered_map',
139
+ 'unordered_set', 'utility', 'valarray', 'variant', 'vector',
140
+ 'version',
141
+ ]);
142
+ /**
143
+ * Check if an import is external (npm package, etc.)
144
+ *
145
+ * `context` is consulted for project-defined path aliases
146
+ * (tsconfig/jsconfig `paths`). Without that check, custom prefixes
147
+ * like `@components/*` would fail the bare-specifier heuristic and
148
+ * be classified as external before alias resolution can run.
149
+ */
150
+ function isExternalImport(importPath, language, context) {
151
+ // Relative imports are not external
152
+ if (importPath.startsWith('.')) {
153
+ return false;
154
+ }
155
+ // Workspace-member imports (`@scope/ui`, `@scope/ui/widgets`) are LOCAL to
156
+ // a monorepo even though they look like bare npm specifiers. Consult the
157
+ // workspace map first so they aren't misclassified as external (#629). The
158
+ // map is null for single-package repos, so this is a no-op there.
159
+ const workspaces = context?.getWorkspacePackages?.();
160
+ if (workspaces && (0, workspace_packages_1.resolveWorkspaceImport)(importPath, workspaces)) {
161
+ return false;
162
+ }
163
+ // Common external patterns
164
+ if (language === 'typescript' || language === 'javascript' || language === 'tsx' || language === 'jsx') {
165
+ // Node built-ins
166
+ if (['fs', 'path', 'os', 'crypto', 'http', 'https', 'url', 'util', 'events', 'stream', 'child_process', 'buffer'].includes(importPath)) {
167
+ return true;
168
+ }
169
+ // Project-defined alias prefix? Treat as local.
170
+ const aliases = context?.getProjectAliases?.();
171
+ if (aliases) {
172
+ for (const pat of aliases.patterns) {
173
+ if (importPath.startsWith(pat.prefix))
174
+ return false;
175
+ }
176
+ }
177
+ // Scoped packages or bare specifiers that don't start with aliases
178
+ if (!importPath.startsWith('@/') && !importPath.startsWith('~/') && !importPath.startsWith('src/')) {
179
+ // Likely an npm package
180
+ return true;
181
+ }
182
+ }
183
+ if (language === 'python') {
184
+ // Standard library modules
185
+ const stdLibs = ['os', 'sys', 'json', 're', 'math', 'datetime', 'collections', 'typing', 'pathlib', 'logging'];
186
+ if (stdLibs.includes(importPath.split('.')[0])) {
187
+ return true;
188
+ }
189
+ }
190
+ if (language === 'go') {
191
+ // Relative imports (rare in idiomatic Go but the grammar allows them).
192
+ if (importPath.startsWith('.')) {
193
+ return false;
194
+ }
195
+ // In-module imports look like `<module-path>/sub/pkg` — local to
196
+ // this project. Without the module-path check we'd flag every
197
+ // cross-package call in a Go monorepo as external (issue #388).
198
+ const mod = context?.getGoModule?.();
199
+ if (mod && (importPath === mod.modulePath || importPath.startsWith(mod.modulePath + '/'))) {
200
+ return false;
201
+ }
202
+ // `internal/` packages stay local even when go.mod is missing —
203
+ // preserves the pre-#388 escape hatch for repos without a parsed module path.
204
+ if (importPath.includes('/internal/')) {
205
+ return false;
206
+ }
207
+ // Anything else is the Go standard library or a third-party module.
208
+ return true;
209
+ }
210
+ if (language === 'c' || language === 'cpp') {
211
+ // C/C++ standard library headers — both C-style (<stdio.h>) and
212
+ // C++-style (<cstdio>, <vector>) forms. Checked against the import
213
+ // path (which the extractor strips of <> or "" delimiters).
214
+ if (C_CPP_STDLIB_HEADERS.has(importPath))
215
+ return true;
216
+ // C++ headers without .h extension (e.g. "vector", "string")
217
+ const withoutExt = importPath.replace(/\.h$/, '');
218
+ if (C_CPP_STDLIB_HEADERS.has(withoutExt))
219
+ return true;
220
+ }
221
+ return false;
222
+ }
223
+ /**
224
+ * Resolve a relative import
225
+ */
226
+ function resolveRelativeImport(importPath, fromDir, language, context) {
227
+ const projectRoot = context.getProjectRoot();
228
+ const extensions = EXTENSION_RESOLUTION[language] || [];
229
+ // Python dotted-relative imports (`from .certs import x`, `from ..pkg.mod
230
+ // import y`): leading dots are PACKAGE levels (1 = current package), and the
231
+ // remainder is a dotted submodule path. `path.resolve(dir, '.certs')` would
232
+ // treat `.certs` as a literal hidden filename, so translate the Python form
233
+ // to a real filesystem-relative path before resolving.
234
+ if (language === 'python' && importPath.startsWith('.')) {
235
+ const dots = importPath.length - importPath.replace(/^\.+/, '').length;
236
+ const up = '../'.repeat(Math.max(0, dots - 1)); // 1 dot = current dir
237
+ const rest = importPath.slice(dots).replace(/\./g, '/'); // 'sub.mod' -> 'sub/mod'
238
+ const pyBase = path.resolve(fromDir, up + rest);
239
+ const pyRel = path.relative(projectRoot, pyBase).replace(/\\/g, '/');
240
+ for (const ext of extensions) {
241
+ if (context.fileExists(pyRel + ext))
242
+ return pyRel + ext;
243
+ }
244
+ if (pyRel && context.fileExists(pyRel))
245
+ return pyRel;
246
+ return null;
247
+ }
248
+ // Try the path as-is first
249
+ const basePath = path.resolve(fromDir, importPath);
250
+ const relativePath = path.relative(projectRoot, basePath).replace(/\\/g, '/');
251
+ // Try each extension
252
+ for (const ext of extensions) {
253
+ const candidatePath = relativePath + ext;
254
+ if (context.fileExists(candidatePath)) {
255
+ return candidatePath;
256
+ }
257
+ }
258
+ // Try without extension (might already have one)
259
+ if (context.fileExists(relativePath)) {
260
+ return relativePath;
261
+ }
262
+ return null;
263
+ }
264
+ /**
265
+ * Resolve an aliased/absolute import.
266
+ *
267
+ * Tries, in order:
268
+ * 1. Project-defined `compilerOptions.paths` (tsconfig/jsconfig).
269
+ * Each pattern can have multiple replacements; tried in tsconfig
270
+ * priority order with extension permutations.
271
+ * 2. The legacy hard-coded fallback list (`@/`, `~/`, `src/`, ...)
272
+ * for projects that have aliases but no tsconfig paths block.
273
+ * 3. Direct path lookup (with extensions).
274
+ */
275
+ function resolveAliasedImport(importPath, projectRoot, language, context) {
276
+ const extensions = EXTENSION_RESOLUTION[language] || [];
277
+ const tryWithExt = (basePath) => {
278
+ for (const ext of extensions) {
279
+ const candidate = basePath + ext;
280
+ if (context.fileExists(candidate))
281
+ return candidate;
282
+ }
283
+ if (context.fileExists(basePath))
284
+ return basePath;
285
+ return null;
286
+ };
287
+ // 1. Project tsconfig/jsconfig paths.
288
+ const aliasMap = context.getProjectAliases?.();
289
+ if (aliasMap) {
290
+ const candidates = (0, path_aliases_1.applyAliases)(importPath, aliasMap, projectRoot);
291
+ for (const c of candidates) {
292
+ const hit = tryWithExt(c);
293
+ if (hit)
294
+ return hit;
295
+ }
296
+ }
297
+ // 1.5 Workspace packages (`@scope/ui/widgets` → `packages/ui/widgets`).
298
+ // Resolves a monorepo member import to the member's directory; the
299
+ // extension/index permutations below then find its barrel (#629).
300
+ const workspaces = context.getWorkspacePackages?.();
301
+ if (workspaces) {
302
+ const base = (0, workspace_packages_1.resolveWorkspaceImport)(importPath, workspaces);
303
+ if (base) {
304
+ const hit = tryWithExt(base);
305
+ if (hit)
306
+ return hit;
307
+ }
308
+ }
309
+ // 2. Hard-coded fallback list. Kept for projects that use these
310
+ // conventional aliases without declaring them in tsconfig.
311
+ const fallbackAliases = {
312
+ '@/': 'src/',
313
+ '~/': 'src/',
314
+ '@src/': 'src/',
315
+ 'src/': 'src/',
316
+ '@app/': 'app/',
317
+ 'app/': 'app/',
318
+ };
319
+ for (const [alias, replacement] of Object.entries(fallbackAliases)) {
320
+ if (importPath.startsWith(alias)) {
321
+ const hit = tryWithExt(importPath.replace(alias, replacement));
322
+ if (hit)
323
+ return hit;
324
+ }
325
+ }
326
+ // 3. Direct path.
327
+ return tryWithExt(importPath);
328
+ }
329
+ /**
330
+ * C/C++ include directory cache (keyed by project root).
331
+ * Loaded once per resolver instance, shared across calls.
332
+ */
333
+ const cppIncludeDirCache = new Map();
334
+ /**
335
+ * Clear the C/C++ include directory cache (call between indexing runs)
336
+ */
337
+ function clearCppIncludeDirCache() {
338
+ cppIncludeDirCache.clear();
339
+ }
340
+ /**
341
+ * Discover C/C++ include search directories for a project.
342
+ *
343
+ * Strategy:
344
+ * 1. Look for compile_commands.json (Clang compilation database) in the
345
+ * project root and common build subdirectories. Parse -I and -isystem
346
+ * flags from compiler commands.
347
+ * 2. If no compilation database is found, probe for common convention
348
+ * directories (include/, src/, lib/, api/) and top-level directories
349
+ * containing .h/.hpp files.
350
+ *
351
+ * Returns paths relative to projectRoot.
352
+ */
353
+ function loadCppIncludeDirs(projectRoot) {
354
+ const cached = cppIncludeDirCache.get(projectRoot);
355
+ if (cached !== undefined)
356
+ return cached;
357
+ const dirs = loadCppIncludeDirsFromCompileDB(projectRoot)
358
+ || loadCppIncludeDirsHeuristic(projectRoot);
359
+ cppIncludeDirCache.set(projectRoot, dirs);
360
+ return dirs;
361
+ }
362
+ /**
363
+ * Try to load include directories from compile_commands.json.
364
+ * Returns null if no compilation database is found (so the heuristic
365
+ * fallback can run). Returns an array (possibly empty) otherwise.
366
+ */
367
+ function loadCppIncludeDirsFromCompileDB(projectRoot) {
368
+ const candidates = [
369
+ path.join(projectRoot, 'compile_commands.json'),
370
+ path.join(projectRoot, 'build', 'compile_commands.json'),
371
+ path.join(projectRoot, 'cmake-build-debug', 'compile_commands.json'),
372
+ path.join(projectRoot, 'cmake-build-release', 'compile_commands.json'),
373
+ path.join(projectRoot, 'out', 'compile_commands.json'),
374
+ ];
375
+ let dbPath;
376
+ for (const c of candidates) {
377
+ try {
378
+ if (fs.existsSync(c)) {
379
+ dbPath = c;
380
+ break;
381
+ }
382
+ }
383
+ catch {
384
+ // ignore
385
+ }
386
+ }
387
+ if (!dbPath)
388
+ return null;
389
+ try {
390
+ const content = fs.readFileSync(dbPath, 'utf-8');
391
+ const entries = JSON.parse(content);
392
+ if (!Array.isArray(entries))
393
+ return null;
394
+ const dirSet = new Set();
395
+ for (const entry of entries) {
396
+ const dir = entry.directory || projectRoot;
397
+ const args = entry.arguments || (entry.command ? shlexSplit(entry.command) : []);
398
+ for (let i = 0; i < args.length; i++) {
399
+ const arg = args[i];
400
+ let includeDir;
401
+ // -I<dir> (no space)
402
+ if (arg.startsWith('-I') && arg.length > 2) {
403
+ includeDir = arg.substring(2);
404
+ }
405
+ // -isystem <dir> (space-separated)
406
+ else if ((arg === '-isystem' || arg === '-I') && i + 1 < args.length) {
407
+ includeDir = args[i + 1];
408
+ i++; // skip next arg
409
+ }
410
+ if (includeDir) {
411
+ // Normalize: resolve relative to the compilation directory
412
+ const absPath = path.isAbsolute(includeDir)
413
+ ? includeDir
414
+ : path.resolve(dir, includeDir);
415
+ const relPath = path.relative(projectRoot, absPath).replace(/\\/g, '/');
416
+ // Skip system directories and paths outside the project
417
+ // (relative paths starting with .. or absolute paths like
418
+ // /usr/include or C:\usr on Windows)
419
+ if (!relPath.startsWith('..') && relPath.length > 0 && !path.isAbsolute(relPath)) {
420
+ dirSet.add(relPath);
421
+ }
422
+ }
423
+ }
424
+ }
425
+ return Array.from(dirSet);
426
+ }
427
+ catch {
428
+ return null;
429
+ }
430
+ }
431
+ /**
432
+ * Minimal shlex-style split for compiler command strings.
433
+ * Handles double-quoted and single-quoted arguments.
434
+ */
435
+ function shlexSplit(cmd) {
436
+ const result = [];
437
+ let i = 0;
438
+ while (i < cmd.length) {
439
+ // Skip whitespace
440
+ while (i < cmd.length && /\s/.test(cmd[i]))
441
+ i++;
442
+ if (i >= cmd.length)
443
+ break;
444
+ const ch = cmd[i];
445
+ if (ch === '"') {
446
+ i++;
447
+ let arg = '';
448
+ while (i < cmd.length && cmd[i] !== '"') {
449
+ if (cmd[i] === '\\' && i + 1 < cmd.length) {
450
+ i++;
451
+ arg += cmd[i];
452
+ }
453
+ else {
454
+ arg += cmd[i];
455
+ }
456
+ i++;
457
+ }
458
+ i++; // closing quote
459
+ result.push(arg);
460
+ }
461
+ else if (ch === "'") {
462
+ i++;
463
+ let arg = '';
464
+ while (i < cmd.length && cmd[i] !== "'") {
465
+ arg += cmd[i];
466
+ i++;
467
+ }
468
+ i++; // closing quote
469
+ result.push(arg);
470
+ }
471
+ else {
472
+ let arg = '';
473
+ while (i < cmd.length && !/\s/.test(cmd[i])) {
474
+ arg += cmd[i];
475
+ i++;
476
+ }
477
+ result.push(arg);
478
+ }
479
+ }
480
+ return result;
481
+ }
482
+ /**
483
+ * Heuristic include directory discovery when no compile_commands.json exists.
484
+ * Checks common convention directories and scans top-level dirs for headers.
485
+ */
486
+ function loadCppIncludeDirsHeuristic(projectRoot) {
487
+ const dirs = [];
488
+ const conventionDirs = ['include', 'src', 'lib', 'api', 'inc'];
489
+ try {
490
+ const entries = fs.readdirSync(projectRoot, { withFileTypes: true });
491
+ for (const entry of entries) {
492
+ if (!entry.isDirectory())
493
+ continue;
494
+ const name = entry.name;
495
+ // Convention directories
496
+ if (conventionDirs.includes(name.toLowerCase())) {
497
+ dirs.push(name);
498
+ continue;
499
+ }
500
+ // Any top-level directory containing .h or .hpp files
501
+ try {
502
+ const subFiles = fs.readdirSync(path.join(projectRoot, name));
503
+ if (subFiles.some(f => /\.(h|hpp|hxx|hh)$/i.test(f))) {
504
+ dirs.push(name);
505
+ }
506
+ }
507
+ catch {
508
+ // ignore permission errors
509
+ }
510
+ }
511
+ }
512
+ catch {
513
+ // ignore
514
+ }
515
+ return dirs;
516
+ }
517
+ /**
518
+ * Resolve a C/C++ include path by searching include directories.
519
+ * Called as a fallback after relative and aliased resolution fail.
520
+ */
521
+ function resolveCppIncludePath(importPath, language, context) {
522
+ const includeDirs = context.getCppIncludeDirs?.() ?? [];
523
+ const extensions = EXTENSION_RESOLUTION[language] ?? [];
524
+ for (const dir of includeDirs) {
525
+ const normalizedDir = dir.replace(/\\/g, '/');
526
+ for (const ext of extensions) {
527
+ const candidate = normalizedDir + '/' + importPath + ext;
528
+ if (context.fileExists(candidate))
529
+ return candidate;
530
+ }
531
+ // Try as-is (already has extension)
532
+ const candidate = normalizedDir + '/' + importPath;
533
+ if (context.fileExists(candidate))
534
+ return candidate;
535
+ }
536
+ return null;
537
+ }
538
+ /**
539
+ * Extract import mappings from a file
540
+ */
541
+ function extractImportMappings(_filePath, content, language) {
542
+ const mappings = [];
543
+ if (language === 'typescript' || language === 'javascript' || language === 'tsx' || language === 'jsx') {
544
+ mappings.push(...extractJSImports(content));
545
+ }
546
+ else if (language === 'svelte' || language === 'vue') {
547
+ // Svelte/Vue single-file components import via plain ES6 inside their
548
+ // `<script>` block. Without this, a `.svelte`/`.vue` consumer produces
549
+ // zero import mappings, so `resolveViaImport` can't run and a barrel
550
+ // import (`import { Foo } from './lib'`) falls back to name-matching —
551
+ // which silently fails whenever the re-export alias differs from the
552
+ // component's real name, yielding a false 0 callers (#629). The ES6
553
+ // import regex only matches `import … from '…'`, so running it over the
554
+ // whole SFC (markup + styles included) is safe.
555
+ mappings.push(...extractJSImports(content));
556
+ }
557
+ else if (language === 'python') {
558
+ mappings.push(...extractPythonImports(content));
559
+ }
560
+ else if (language === 'go') {
561
+ mappings.push(...extractGoImports(content));
562
+ }
563
+ else if (language === 'java' || language === 'kotlin') {
564
+ mappings.push(...extractJavaImports(content));
565
+ }
566
+ else if (language === 'php') {
567
+ mappings.push(...extractPHPImports(content));
568
+ }
569
+ else if (language === 'c' || language === 'cpp') {
570
+ mappings.push(...extractCppImports(content));
571
+ }
572
+ return mappings;
573
+ }
574
+ /**
575
+ * Extract JS/TS import mappings
576
+ */
577
+ function extractJSImports(content) {
578
+ const mappings = [];
579
+ // ES6 imports
580
+ const importRegex = /import\s+(?:(\w+)\s*,?\s*)?(?:\{([^}]+)\})?\s*(?:(\*)\s+as\s+(\w+))?\s*from\s*['"]([^'"]+)['"]/g;
581
+ let match;
582
+ while ((match = importRegex.exec(content)) !== null) {
583
+ const [, defaultImport, namedImports, star, namespaceAlias, source] = match;
584
+ // Default import
585
+ if (defaultImport) {
586
+ mappings.push({
587
+ localName: defaultImport,
588
+ exportedName: 'default',
589
+ source: source,
590
+ isDefault: true,
591
+ isNamespace: false,
592
+ });
593
+ }
594
+ // Named imports
595
+ if (namedImports) {
596
+ const names = namedImports.split(',').map((s) => s.trim());
597
+ for (const name of names) {
598
+ const aliasMatch = name.match(/(\w+)\s+as\s+(\w+)/);
599
+ if (aliasMatch) {
600
+ mappings.push({
601
+ localName: aliasMatch[2],
602
+ exportedName: aliasMatch[1],
603
+ source: source,
604
+ isDefault: false,
605
+ isNamespace: false,
606
+ });
607
+ }
608
+ else if (name) {
609
+ mappings.push({
610
+ localName: name,
611
+ exportedName: name,
612
+ source: source,
613
+ isDefault: false,
614
+ isNamespace: false,
615
+ });
616
+ }
617
+ }
618
+ }
619
+ // Namespace import
620
+ if (star && namespaceAlias) {
621
+ mappings.push({
622
+ localName: namespaceAlias,
623
+ exportedName: '*',
624
+ source: source,
625
+ isDefault: false,
626
+ isNamespace: true,
627
+ });
628
+ }
629
+ }
630
+ // Require statements
631
+ const requireRegex = /(?:const|let|var)\s+(?:(\w+)|{([^}]+)})\s*=\s*require\(['"]([^'"]+)['"]\)/g;
632
+ while ((match = requireRegex.exec(content)) !== null) {
633
+ const [, defaultName, destructured, source] = match;
634
+ if (defaultName) {
635
+ mappings.push({
636
+ localName: defaultName,
637
+ exportedName: 'default',
638
+ source: source,
639
+ isDefault: true,
640
+ isNamespace: false,
641
+ });
642
+ }
643
+ if (destructured) {
644
+ const names = destructured.split(',').map((s) => s.trim());
645
+ for (const name of names) {
646
+ const aliasMatch = name.match(/(\w+)\s*:\s*(\w+)/);
647
+ if (aliasMatch) {
648
+ mappings.push({
649
+ localName: aliasMatch[2],
650
+ exportedName: aliasMatch[1],
651
+ source: source,
652
+ isDefault: false,
653
+ isNamespace: false,
654
+ });
655
+ }
656
+ else if (name) {
657
+ mappings.push({
658
+ localName: name,
659
+ exportedName: name,
660
+ source: source,
661
+ isDefault: false,
662
+ isNamespace: false,
663
+ });
664
+ }
665
+ }
666
+ }
667
+ }
668
+ return mappings;
669
+ }
670
+ /**
671
+ * Extract Python import mappings
672
+ */
673
+ function extractPythonImports(content) {
674
+ const mappings = [];
675
+ // from X import Y
676
+ const fromImportRegex = /from\s+([\w.]+)\s+import\s+([^#\n]+)/g;
677
+ let match;
678
+ while ((match = fromImportRegex.exec(content)) !== null) {
679
+ const [, source, imports] = match;
680
+ const names = imports.split(',').map((s) => s.trim());
681
+ for (const name of names) {
682
+ const aliasMatch = name.match(/(\w+)\s+as\s+(\w+)/);
683
+ if (aliasMatch) {
684
+ mappings.push({
685
+ localName: aliasMatch[2],
686
+ exportedName: aliasMatch[1],
687
+ source: source,
688
+ isDefault: false,
689
+ isNamespace: false,
690
+ });
691
+ }
692
+ else if (name && name !== '*') {
693
+ mappings.push({
694
+ localName: name,
695
+ exportedName: name,
696
+ source: source,
697
+ isDefault: false,
698
+ isNamespace: false,
699
+ });
700
+ }
701
+ }
702
+ }
703
+ // import X
704
+ const importRegex = /^import\s+([\w.]+)(?:\s+as\s+(\w+))?/gm;
705
+ while ((match = importRegex.exec(content)) !== null) {
706
+ const [, source, alias] = match;
707
+ const localName = alias || source.split('.').pop();
708
+ mappings.push({
709
+ localName,
710
+ exportedName: '*',
711
+ source: source,
712
+ isDefault: false,
713
+ isNamespace: true,
714
+ });
715
+ }
716
+ return mappings;
717
+ }
718
+ /**
719
+ * Extract Go import mappings
720
+ */
721
+ function extractGoImports(content) {
722
+ const mappings = [];
723
+ // import "path" or import alias "path"
724
+ const singleImportRegex = /import\s+(?:(\w+)\s+)?["']([^"']+)["']/g;
725
+ let match;
726
+ while ((match = singleImportRegex.exec(content)) !== null) {
727
+ const [, alias, source] = match;
728
+ const packageName = source.split('/').pop();
729
+ mappings.push({
730
+ localName: alias || packageName,
731
+ exportedName: '*',
732
+ source: source,
733
+ isDefault: false,
734
+ isNamespace: true,
735
+ });
736
+ }
737
+ // import ( ... ) block
738
+ const blockImportRegex = /import\s*\(\s*([^)]+)\s*\)/gs;
739
+ while ((match = blockImportRegex.exec(content)) !== null) {
740
+ const block = match[1];
741
+ const lineRegex = /(?:(\w+)\s+)?["']([^"']+)["']/g;
742
+ let lineMatch;
743
+ while ((lineMatch = lineRegex.exec(block)) !== null) {
744
+ const [, alias, source] = lineMatch;
745
+ const packageName = source.split('/').pop();
746
+ mappings.push({
747
+ localName: alias || packageName,
748
+ exportedName: '*',
749
+ source: source,
750
+ isDefault: false,
751
+ isNamespace: true,
752
+ });
753
+ }
754
+ }
755
+ return mappings;
756
+ }
757
+ /**
758
+ * Extract Java / Kotlin import mappings.
759
+ *
760
+ * Java/Kotlin imports carry the full qualified name of the imported
761
+ * symbol — `import com.example.dao.converter.FooConverter;` — which is
762
+ * exactly the disambiguation signal we need when two packages both
763
+ * declare a `FooConverter`. Pre-#314 the resolver had no Java branch
764
+ * here at all, so this mapping was empty and cross-module name
765
+ * collisions were resolved by file-path proximity (often wrongly).
766
+ *
767
+ * `import static com.example.Foo.bar;` is parsed as a local-name `bar`
768
+ * pointing at FQN `com.example.Foo.bar` so static-method call sites
769
+ * (`bar(...)`) can resolve through the same import lookup.
770
+ */
771
+ function extractJavaImports(content) {
772
+ const mappings = [];
773
+ // Strip line and block comments so `// import foo;` doesn't false-match.
774
+ const stripped = content
775
+ .replace(/\/\*[\s\S]*?\*\//g, '')
776
+ .replace(/\/\/[^\n]*/g, '');
777
+ // `import [static] <fqn>[.*];`
778
+ const re = /^\s*import\s+(static\s+)?([\w.]+(?:\.\*)?)\s*;/gm;
779
+ let match;
780
+ while ((match = re.exec(stripped)) !== null) {
781
+ const fqn = match[2];
782
+ // `import com.example.*;` — wildcard. We can't materialize a single
783
+ // local name; skip and let name-matching handle members reachable
784
+ // through the wildcard. (Future enhancement: enumerate package files.)
785
+ if (fqn.endsWith('.*'))
786
+ continue;
787
+ const parts = fqn.split('.');
788
+ const localName = parts[parts.length - 1];
789
+ if (!localName)
790
+ continue;
791
+ mappings.push({
792
+ localName,
793
+ exportedName: localName,
794
+ source: fqn,
795
+ isDefault: false,
796
+ isNamespace: false,
797
+ });
798
+ }
799
+ return mappings;
800
+ }
801
+ /**
802
+ * Extract PHP import mappings (use statements)
803
+ */
804
+ function extractPHPImports(content) {
805
+ const mappings = [];
806
+ // use Namespace\Class; or use Namespace\Class as Alias;
807
+ const useRegex = /use\s+([\w\\]+)(?:\s+as\s+(\w+))?;/g;
808
+ let match;
809
+ while ((match = useRegex.exec(content)) !== null) {
810
+ const [, fullPath, alias] = match;
811
+ const className = fullPath.split('\\').pop();
812
+ mappings.push({
813
+ localName: alias || className,
814
+ exportedName: className,
815
+ source: fullPath,
816
+ isDefault: false,
817
+ isNamespace: false,
818
+ });
819
+ }
820
+ return mappings;
821
+ }
822
+ /**
823
+ * Extract C/C++ import mappings from #include directives.
824
+ *
825
+ * #include brings all symbols from the included header into scope
826
+ * (namespace import), so each mapping uses isNamespace: true and
827
+ * exportedName: '*'. The localName is set to the header's basename
828
+ * without extension so that symbol references like `MyClass` can
829
+ * match against any include that might provide it.
830
+ */
831
+ function extractCppImports(content) {
832
+ const mappings = [];
833
+ // Match both #include <...> and #include "..."
834
+ const includeRegex = /^\s*#\s*include\s+[<"]([^>"]+)[>"]/gm;
835
+ let match;
836
+ while ((match = includeRegex.exec(content)) !== null) {
837
+ const modulePath = match[1];
838
+ // Basename without extension for localName matching
839
+ const basename = modulePath.split('/').pop().replace(/\.(h|hpp|hxx|hh|inl|ipp|cxx|cc|cpp)$/, '');
840
+ mappings.push({
841
+ localName: basename || modulePath,
842
+ exportedName: '*',
843
+ source: modulePath,
844
+ isDefault: false,
845
+ isNamespace: true,
846
+ });
847
+ }
848
+ return mappings;
849
+ }
850
+ // Cache import mappings per file to avoid re-reading and re-parsing
851
+ const importMappingCache = new Map();
852
+ /**
853
+ * Clear the import mapping cache (call between indexing runs)
854
+ */
855
+ function clearImportMappingCache() {
856
+ importMappingCache.clear();
857
+ cppIncludeDirCache.clear();
858
+ }
859
+ /**
860
+ * Strip JS line + block comments from `content` while preserving
861
+ * string literals (so `"//"` inside a string stays intact). Used by
862
+ * {@link extractReExports} so commented-out export-from statements
863
+ * don't generate phantom re-export edges.
864
+ *
865
+ * Scanner is deliberately small: it only tracks the three contexts
866
+ * relevant for JS/TS — single-quote string, double-quote string, and
867
+ * template literal. Comment recognition is the JS spec subset, no
868
+ * regex-literal awareness (which is fine for our use case: we don't
869
+ * apply this to function bodies, only to top-level files).
870
+ */
871
+ function stripJsComments(content) {
872
+ let out = '';
873
+ let i = 0;
874
+ let str = null;
875
+ while (i < content.length) {
876
+ const ch = content[i];
877
+ if (str !== null) {
878
+ out += ch;
879
+ if (ch === '\\' && i + 1 < content.length) {
880
+ out += content[i + 1];
881
+ i += 2;
882
+ continue;
883
+ }
884
+ if (ch === str)
885
+ str = null;
886
+ i++;
887
+ continue;
888
+ }
889
+ if (ch === '"' || ch === "'" || ch === '`') {
890
+ str = ch;
891
+ out += ch;
892
+ i++;
893
+ continue;
894
+ }
895
+ if (ch === '/' && content[i + 1] === '/') {
896
+ while (i < content.length && content[i] !== '\n')
897
+ i++;
898
+ continue;
899
+ }
900
+ if (ch === '/' && content[i + 1] === '*') {
901
+ i += 2;
902
+ while (i < content.length && !(content[i] === '*' && content[i + 1] === '/'))
903
+ i++;
904
+ i += 2;
905
+ continue;
906
+ }
907
+ out += ch;
908
+ i++;
909
+ }
910
+ return out;
911
+ }
912
+ /**
913
+ * Extract JS/TS re-export declarations from `content`.
914
+ *
915
+ * Recognised forms:
916
+ * export { foo } from './a';
917
+ * export { foo as bar } from './a';
918
+ * export * from './a';
919
+ * export * as ns from './a'; (treated as wildcard for chasing)
920
+ * export { default as Foo } from './a';
921
+ *
922
+ * The walker intentionally stays regex-based — the import-resolver
923
+ * elsewhere in this file already chooses regex over a fresh
924
+ * tree-sitter pass, and this function shares that trade-off. Errors
925
+ * fall through silently; resolution simply skips the broken file.
926
+ */
927
+ function extractReExports(content, language) {
928
+ if (language !== 'typescript' &&
929
+ language !== 'javascript' &&
930
+ language !== 'tsx' &&
931
+ language !== 'jsx') {
932
+ return [];
933
+ }
934
+ const out = [];
935
+ // Pre-strip block comments + line comments so a commented-out
936
+ // `// export { x } from '...'` doesn't produce a phantom edge.
937
+ // (Template literals are still a possible source of false positives;
938
+ // a project that builds export statements as runtime strings is
939
+ // out of scope.)
940
+ const cleaned = stripJsComments(content);
941
+ // Wildcard: `export * from '...'` or `export * as ns from '...'`
942
+ const wildcardRe = /export\s*\*(?:\s+as\s+\w+)?\s*from\s*['"]([^'"]+)['"]/g;
943
+ let m;
944
+ while ((m = wildcardRe.exec(cleaned)) !== null) {
945
+ out.push({ kind: 'wildcard', source: m[1] });
946
+ }
947
+ // Named: `export { a, b as c } from '...'`
948
+ const namedRe = /export\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g;
949
+ while ((m = namedRe.exec(cleaned)) !== null) {
950
+ const inner = m[1];
951
+ const source = m[2];
952
+ for (const raw of inner.split(',')) {
953
+ const item = raw.trim();
954
+ if (!item)
955
+ continue;
956
+ const aliasMatch = item.match(/^(\w+)\s+as\s+(\w+)$/);
957
+ if (aliasMatch) {
958
+ out.push({
959
+ kind: 'named',
960
+ exportedName: aliasMatch[2],
961
+ originalName: aliasMatch[1],
962
+ source,
963
+ });
964
+ }
965
+ else if (/^\w+$/.test(item)) {
966
+ out.push({
967
+ kind: 'named',
968
+ exportedName: item,
969
+ originalName: item,
970
+ source,
971
+ });
972
+ }
973
+ }
974
+ }
975
+ return out;
976
+ }
977
+ /**
978
+ * Resolve a reference using import mappings
979
+ */
980
+ /**
981
+ * JVM (Java / Kotlin) imports use fully-qualified names (`import
982
+ * com.example.foo.Bar`) decoupled from filenames, so the JS/Python
983
+ * style filesystem path lookup misses them whenever the file isn't
984
+ * named after its primary symbol (Kotlin `Utils.kt` exporting `Bar`,
985
+ * top-level fns, extension fns). Resolve them through the
986
+ * `qualifiedName` index instead — populated by the package_header /
987
+ * package_declaration namespace wrappers in the extractor.
988
+ */
989
+ function resolveJvmImport(ref, context) {
990
+ if (ref.referenceKind !== 'imports')
991
+ return null;
992
+ if (ref.language !== 'java' && ref.language !== 'kotlin')
993
+ return null;
994
+ const fqn = ref.referenceName;
995
+ const lastDot = fqn.lastIndexOf('.');
996
+ if (lastDot <= 0)
997
+ return null;
998
+ const pkg = fqn.substring(0, lastDot);
999
+ const sym = fqn.substring(lastDot + 1);
1000
+ // Wildcard imports (`com.example.*`) deliberately punt to name-matcher.
1001
+ if (sym === '*')
1002
+ return null;
1003
+ const candidates = context.getNodesByQualifiedName(`${pkg}::${sym}`);
1004
+ if (candidates.length === 0)
1005
+ return null;
1006
+ // Kotlin Multiplatform: an `expect` declaration and its `actual`s share one
1007
+ // FQN across source sets (commonMain / androidMain / appleMain). Taking the
1008
+ // first candidate let a single platform `actual` absorb every common-side
1009
+ // import, so the `expect` (the canonical API a commonMain file imports)
1010
+ // looked unused. Prefer the candidate CLOSEST to the importing file by
1011
+ // directory proximity — a commonMain import resolves to the commonMain
1012
+ // declaration — with the `expect` side as a tiebreak.
1013
+ const best = candidates.length === 1 ? candidates[0] : pickClosestJvmCandidate(candidates, ref.filePath);
1014
+ return {
1015
+ original: ref,
1016
+ targetNodeId: best.id,
1017
+ confidence: 0.95,
1018
+ resolvedBy: 'import',
1019
+ };
1020
+ }
1021
+ /**
1022
+ * Pick the same-FQN candidate closest to `fromPath` by shared directory
1023
+ * prefix, preferring an `expect` declaration on a tie. Used to keep a Kotlin
1024
+ * Multiplatform `expect`/`actual` import resolving within the importer's own
1025
+ * source set instead of an arbitrary platform `actual`.
1026
+ */
1027
+ function pickClosestJvmCandidate(candidates, fromPath) {
1028
+ const fromDirs = fromPath.split('/').slice(0, -1);
1029
+ const sharedPrefix = (p) => {
1030
+ const d = p.split('/').slice(0, -1);
1031
+ let shared = 0;
1032
+ for (let i = 0; i < Math.min(fromDirs.length, d.length); i++) {
1033
+ if (fromDirs[i] === d[i])
1034
+ shared++;
1035
+ else
1036
+ break;
1037
+ }
1038
+ return shared;
1039
+ };
1040
+ const isExpect = (n) => Array.isArray(n.decorators) && n.decorators.includes('expect');
1041
+ let best = candidates[0];
1042
+ let bestProx = sharedPrefix(best.filePath);
1043
+ for (let i = 1; i < candidates.length; i++) {
1044
+ const c = candidates[i];
1045
+ const prox = sharedPrefix(c.filePath);
1046
+ if (prox > bestProx || (prox === bestProx && isExpect(c) && !isExpect(best))) {
1047
+ best = c;
1048
+ bestProx = prox;
1049
+ }
1050
+ }
1051
+ return best;
1052
+ }
1053
+ function resolveViaImport(ref, context) {
1054
+ // C/C++ #include references — resolve directly to the included file
1055
+ // (file→file edge), bypassing symbol lookup. The extractor emits these
1056
+ // with `referenceKind: 'imports'` and `referenceName: <include path>`
1057
+ // (e.g. "uint256.h" or "common/args.h"). Without this branch the
1058
+ // include-dir scan path inside resolveImportPath never produces an
1059
+ // edge — resolveViaImport's symbol lookup below would search the
1060
+ // resolved file for a symbol named like the file extension and fail.
1061
+ if ((ref.language === 'c' || ref.language === 'cpp') && ref.referenceKind === 'imports') {
1062
+ // C/C++ quoted includes (`#include "X.h"`) resolve relative to the
1063
+ // INCLUDING file's own directory first (the C standard's quoted-include
1064
+ // search order). Prefer a same-directory header over an -I directory or a
1065
+ // same-named header on another platform (windows/code/RNCAsyncStorage.h vs
1066
+ // apple/.../RNCAsyncStorage.h) — the include-dir heuristic below would
1067
+ // otherwise pick an arbitrary same-named header, leaving the real local one
1068
+ // with no dependents.
1069
+ const slash = ref.filePath.lastIndexOf('/');
1070
+ const fromDir = slash >= 0 ? ref.filePath.slice(0, slash) : '';
1071
+ const siblingPath = path.posix.normalize(fromDir ? `${fromDir}/${ref.referenceName}` : ref.referenceName);
1072
+ const siblingBase = siblingPath.split('/').pop();
1073
+ const sibling = context
1074
+ .getNodesByName(siblingBase)
1075
+ .find((n) => n.kind === 'file' && n.filePath === siblingPath);
1076
+ if (sibling) {
1077
+ return { original: ref, targetNodeId: sibling.id, confidence: 0.92, resolvedBy: 'import' };
1078
+ }
1079
+ const resolvedPath = resolveImportPath(ref.referenceName, ref.filePath, ref.language, context);
1080
+ if (!resolvedPath)
1081
+ return null;
1082
+ const basename = resolvedPath.split('/').pop();
1083
+ const fileNodes = context.getNodesByName(basename).filter((n) => n.kind === 'file');
1084
+ const fileNode = fileNodes.find((n) => n.filePath === resolvedPath);
1085
+ if (fileNode) {
1086
+ return {
1087
+ original: ref,
1088
+ targetNodeId: fileNode.id,
1089
+ confidence: 0.9,
1090
+ resolvedBy: 'import',
1091
+ };
1092
+ }
1093
+ return null;
1094
+ }
1095
+ // Use cached import mappings (avoids re-reading and re-parsing per ref)
1096
+ const imports = context.getImportMappings(ref.filePath, ref.language);
1097
+ if (imports.length === 0 && !context.readFile(ref.filePath)) {
1098
+ return null;
1099
+ }
1100
+ // Go cross-package calls: `pkga.FuncX(...)` extracts to referenceName
1101
+ // `pkga.FuncX` and the import `github.com/example/myproject/pkga`
1102
+ // maps to a *package directory* containing one or more .go files.
1103
+ // The generic file-based lookup below can't follow that — issue #388.
1104
+ if (ref.language === 'go') {
1105
+ const goResult = resolveGoCrossPackageReference(ref, imports, context);
1106
+ if (goResult)
1107
+ return goResult;
1108
+ }
1109
+ // Java / Kotlin: imports are FQNs (`import com.example.Foo;`) — no
1110
+ // resolvable file path the JS/TS-style chain below could follow. Look
1111
+ // up the symbol by name and filter to the candidate whose file path
1112
+ // matches the imported FQN. This is the disambiguation signal that
1113
+ // breaks the same-name class collision the path-proximity matcher
1114
+ // can't resolve (issue #314).
1115
+ if (ref.language === 'java' || ref.language === 'kotlin') {
1116
+ const javaResult = resolveJavaImportedReference(ref, imports, context);
1117
+ if (javaResult)
1118
+ return javaResult;
1119
+ }
1120
+ // Python qualified access through an imported MODULE: `certs.where()` after
1121
+ // `from . import certs`, `mod.func()` after `import mod`. The receiver names a
1122
+ // submodule (a file), not a symbol, so the generic symbol lookup below would
1123
+ // search the *package* for `certs` instead of looking inside the module.
1124
+ if (ref.language === 'python') {
1125
+ const pyResult = resolvePythonModuleMember(ref, imports, context);
1126
+ if (pyResult)
1127
+ return pyResult;
1128
+ // Absolute dotted module import: `import conduit.apps.articles.signals`
1129
+ // (the standard Django AppConfig.ready() signal-registration pattern, and
1130
+ // any side-effect `import pkg.mod`). Map the dotted path to its file.
1131
+ const pyModResult = resolvePythonAbsoluteModule(ref, context);
1132
+ if (pyModResult)
1133
+ return pyModResult;
1134
+ }
1135
+ // Rust qualified path: resolve the module prefix of `crate::m::Item` /
1136
+ // `self::sub::Item` / `super::m::func` to a file, then find the leaf symbol in
1137
+ // it. Disambiguates common-name `pub use self::read::read` re-exports that
1138
+ // name-matching would land on the wrong same-named symbol.
1139
+ if (ref.language === 'rust' && ref.referenceName.includes('::')) {
1140
+ const rustResult = resolveRustPathReference(ref, context);
1141
+ if (rustResult)
1142
+ return rustResult;
1143
+ }
1144
+ // Lua / Luau `require(...)`: a dotted module path (`a.b.c` from
1145
+ // `require("a.b.c")`) or an instance-path leaf (`Signal` from
1146
+ // `require(script.Parent.Signal)`) — map it to a module file. There's no static
1147
+ // import statement, so the generic path-matcher can't bridge the dot↔slash /
1148
+ // leaf↔basename gap; resolve it explicitly to the module file.
1149
+ if ((ref.language === 'lua' || ref.language === 'luau') && ref.referenceKind === 'imports') {
1150
+ const luaResult = resolveLuaRequire(ref, context);
1151
+ if (luaResult)
1152
+ return luaResult;
1153
+ }
1154
+ // Whole-module / namespace imports → link the importing file to the module
1155
+ // file. Python `from . import certs` / `import mod`, and TS/JS `import * as ns
1156
+ // from './x'` (so a namespace touched only via a value-member read still
1157
+ // records the dependency). A named TS/JS import returns null here and falls
1158
+ // through to symbol resolution below.
1159
+ if (ref.language === 'python' ||
1160
+ ref.language === 'typescript' ||
1161
+ ref.language === 'tsx' ||
1162
+ ref.language === 'javascript' ||
1163
+ ref.language === 'jsx') {
1164
+ const moduleFile = resolveModuleImportToFile(ref, imports, context);
1165
+ if (moduleFile)
1166
+ return moduleFile;
1167
+ }
1168
+ // Check if the reference name matches any import
1169
+ for (const imp of imports) {
1170
+ if (imp.localName === ref.referenceName || ref.referenceName.startsWith(imp.localName + '.')) {
1171
+ // Resolve the import path
1172
+ const resolvedPath = resolveImportPath(imp.source, ref.filePath, ref.language, context);
1173
+ if (resolvedPath) {
1174
+ const exportedName = imp.isDefault ? 'default' : imp.exportedName;
1175
+ const memberName = imp.isNamespace
1176
+ ? ref.referenceName.replace(imp.localName + '.', '')
1177
+ : null;
1178
+ const targetNode = findExportedSymbol(resolvedPath, { isDefault: imp.isDefault, isNamespace: imp.isNamespace, exportedName, memberName }, ref.language, context, new Set());
1179
+ if (targetNode) {
1180
+ return {
1181
+ original: ref,
1182
+ targetNodeId: targetNode.id,
1183
+ confidence: 0.9,
1184
+ resolvedBy: 'import',
1185
+ };
1186
+ }
1187
+ }
1188
+ }
1189
+ }
1190
+ return null;
1191
+ }
1192
+ /**
1193
+ * Resolve a Python qualified reference whose receiver is an imported MODULE:
1194
+ * `certs.where()` after `from . import certs`, `mod.func()` after `import mod`
1195
+ * or `from pkg import mod`. The receiver names a submodule (a file), not a
1196
+ * symbol, so the generic symbol lookup in `resolveViaImport` can't follow it —
1197
+ * it would search the *package* for `certs`/`mod` instead of looking inside the
1198
+ * module. This is the Python half of the cross-package qualified-call problem
1199
+ * (cf. `resolveGoCrossPackageReference` for Go's `pkg.Func`, issue #388).
1200
+ *
1201
+ * Builds the module's dotted import path from the binding — `from . import
1202
+ * certs` → `.certs`; `from pkg import mod` → `pkg.mod`; `import mod` → `mod` —
1203
+ * resolves it to the module file, and finds the member defined there. Returns
1204
+ * null when no module file exists at that path, so attribute access on an
1205
+ * imported *value* (`helper.attr` where `helper` is a function) falls through
1206
+ * to the other strategies untouched.
1207
+ */
1208
+ function resolvePythonModuleMember(ref, imports, context) {
1209
+ const dotIdx = ref.referenceName.indexOf('.');
1210
+ if (dotIdx <= 0)
1211
+ return null;
1212
+ const receiver = ref.referenceName.substring(0, dotIdx);
1213
+ // The immediate member of the module (first segment after the receiver).
1214
+ const member = ref.referenceName.substring(dotIdx + 1).split('.')[0];
1215
+ if (!member)
1216
+ return null;
1217
+ for (const imp of imports) {
1218
+ if (imp.localName !== receiver)
1219
+ continue;
1220
+ // `import mod` / `import numpy as np` bind the module at `source` itself;
1221
+ // `from . import certs` / `from pkg import mod` bind a SUBMODULE whose
1222
+ // dotted path is the source joined with the imported name.
1223
+ const modulePath = imp.isNamespace
1224
+ ? imp.source
1225
+ : imp.source.endsWith('.')
1226
+ ? imp.source + imp.localName
1227
+ : imp.source + '.' + imp.localName;
1228
+ // resolveImportPath only maps RELATIVE dotted paths (`.mod`, `..pkg.mod`); an
1229
+ // ABSOLUTE package path (`pkg.module` from `from pkg import module`, or a bare
1230
+ // `import pkg.mod`) resolves to null there, so fall back to the dotted-module
1231
+ // file lookup — the same asymmetry resolveModuleImportToFile already handles
1232
+ // for the file→file import edge. Without this, a `module.func()` call after
1233
+ // `from pkg import module` dropped its `calls` edge even though the import
1234
+ // edge resolved (#578).
1235
+ let resolvedPath = resolveImportPath(modulePath, ref.filePath, ref.language, context);
1236
+ if (!resolvedPath) {
1237
+ resolvedPath = findPythonModuleFile(modulePath, context, ref.filePath)?.filePath ?? null;
1238
+ }
1239
+ if (!resolvedPath || resolvedPath === ref.filePath)
1240
+ continue;
1241
+ // Find the member as a top-level definition in the module file. Exclude
1242
+ // `method` so `mod.foo` never lands on a same-named class method.
1243
+ const target = context.getNodesInFile(resolvedPath).find((n) => n.name === member &&
1244
+ (n.kind === 'function' ||
1245
+ n.kind === 'class' ||
1246
+ n.kind === 'variable' ||
1247
+ n.kind === 'constant'));
1248
+ if (target) {
1249
+ return { original: ref, targetNodeId: target.id, confidence: 0.85, resolvedBy: 'import' };
1250
+ }
1251
+ }
1252
+ return null;
1253
+ }
1254
+ /**
1255
+ * Resolve a whole-MODULE import to that module's file (a file→file dependency).
1256
+ * The imported name is a module, not a symbol, so there's nothing to resolve to
1257
+ * — but importing a module IS a dependency on it. Covers:
1258
+ * - Python submodule imports — `from . import certs`, `from pkg import sub`;
1259
+ * - namespace imports — Python `import mod` / `import numpy as np`, and
1260
+ * TS/JS `import * as ns from './x'`.
1261
+ *
1262
+ * It is also the robust backstop for {@link resolvePythonModuleMember} and for
1263
+ * TS namespace usage: it records the dependency even when the used member is
1264
+ * re-exported elsewhere (requests' `certs.where`, re-exported from `certifi`),
1265
+ * the usage is module-level code that isn't extracted as a call, or a TS
1266
+ * namespace is touched only via a value-member read (`ns.SOME_CONST`).
1267
+ *
1268
+ * Only fires for dot-free `imports`-kind refs whose module path resolves to a
1269
+ * real file. A NAMED TS/JS import (`import { widget }`) is not a module, so it
1270
+ * returns null and normal symbol resolution handles it.
1271
+ */
1272
+ /**
1273
+ * Resolve a Lua/Luau `require(...)` to its module file. The reference name is
1274
+ * either a dotted module path (`telescope.config` → `telescope/config.lua`) or a
1275
+ * Roblox instance-path leaf (`Signal` from `require(script.Parent.Signal)` →
1276
+ * `Signal.luau`). We try `<path>.lua|.luau` and `<path>/init.lua|.luau`, matched
1277
+ * by path suffix (the module root — `lua/`, `src/`, … — is project-specific).
1278
+ * Among suffix matches, the one sharing the longest directory prefix with the
1279
+ * requiring file wins (instance-path requires resolve within the same package).
1280
+ */
1281
+ function resolveLuaRequire(ref, context) {
1282
+ const name = ref.referenceName;
1283
+ if (!name)
1284
+ return null;
1285
+ const base = name.includes('.') ? name.replace(/\./g, '/') : name;
1286
+ const suffixes = [`${base}.lua`, `${base}.luau`, `${base}/init.lua`, `${base}/init.luau`];
1287
+ const files = context.getAllFiles();
1288
+ const shared = (a, b) => {
1289
+ let i = 0;
1290
+ while (i < a.length && i < b.length && a[i] === b[i])
1291
+ i++;
1292
+ return i;
1293
+ };
1294
+ for (const suffix of suffixes) {
1295
+ const matches = files.filter((f) => f === suffix || f.endsWith('/' + suffix));
1296
+ if (matches.length === 0)
1297
+ continue;
1298
+ matches.sort((x, y) => shared(y, ref.filePath) - shared(x, ref.filePath));
1299
+ const best = matches[0];
1300
+ if (best === ref.filePath)
1301
+ continue;
1302
+ const fileNode = context.getNodesInFile(best).find((n) => n.kind === 'file');
1303
+ if (fileNode) {
1304
+ // Confidence ≥ 0.9 so this deterministic path/suffix match wins over
1305
+ // name-matching, which otherwise resolves the require to the import node
1306
+ // itself (a same-name self-match).
1307
+ return { original: ref, targetNodeId: fileNode.id, confidence: 0.9, resolvedBy: 'import' };
1308
+ }
1309
+ }
1310
+ return null;
1311
+ }
1312
+ function resolveModuleImportToFile(ref, imports, context) {
1313
+ if (ref.referenceKind !== 'imports')
1314
+ return null;
1315
+ if (ref.referenceName.includes('.'))
1316
+ return null;
1317
+ for (const imp of imports) {
1318
+ if (imp.localName !== ref.referenceName)
1319
+ continue;
1320
+ let modulePath;
1321
+ if (imp.isNamespace || imp.isDefault) {
1322
+ // `import * as ns from './x'` (namespace) or `import x from './x'`
1323
+ // (default) — the dependency is on the MODULE FILE. A default import binds
1324
+ // a (possibly renamed) local to whatever the module's default export is
1325
+ // (`import articlesController from './article.controller'` ← `export
1326
+ // default router`), so the binding name can't be found as a symbol — link
1327
+ // the file the import resolves to instead. External modules don't resolve
1328
+ // (no file), so `import React from 'react'` creates no edge.
1329
+ modulePath = imp.source;
1330
+ }
1331
+ else if (ref.language === 'python') {
1332
+ // `from . import certs` — the imported NAME is a submodule of the source.
1333
+ modulePath = imp.source.endsWith('.')
1334
+ ? imp.source + imp.localName
1335
+ : imp.source + '.' + imp.localName;
1336
+ }
1337
+ else {
1338
+ // A named TS/JS import binds a symbol, not a module — leave it alone.
1339
+ continue;
1340
+ }
1341
+ const resolvedPath = resolveImportPath(modulePath, ref.filePath, ref.language, context);
1342
+ if (resolvedPath && resolvedPath !== ref.filePath) {
1343
+ const fileNode = context.getNodesInFile(resolvedPath).find((n) => n.kind === 'file');
1344
+ if (fileNode) {
1345
+ return { original: ref, targetNodeId: fileNode.id, confidence: 0.9, resolvedBy: 'import' };
1346
+ }
1347
+ }
1348
+ // Python absolute `from a.b import submodule` (a FastAPI router aggregator's
1349
+ // `from app.api.routes import authentication`): resolveImportPath only maps
1350
+ // RELATIVE dotted paths to a file, so resolve the absolute dotted module
1351
+ // directly to its file node.
1352
+ if (ref.language === 'python') {
1353
+ const modFile = findPythonModuleFile(modulePath, context, ref.filePath);
1354
+ if (modFile) {
1355
+ return { original: ref, targetNodeId: modFile.id, confidence: 0.9, resolvedBy: 'import' };
1356
+ }
1357
+ }
1358
+ }
1359
+ return null;
1360
+ }
1361
+ /**
1362
+ * Find the file node for a Python dotted module path `a.b.c` — a module file
1363
+ * ending in `a/b/c.py`, or a package `a/b/c/__init__.py` (suffix-matched, so a
1364
+ * package rooted under `src/` etc. still resolves). Returns null for
1365
+ * stdlib/external modules (no matching repo file node), so `import os` creates
1366
+ * no edge. Shared by absolute `import a.b.c` and absolute `from a.b import c`
1367
+ * (where `c` is a submodule) resolution.
1368
+ */
1369
+ function findPythonModuleFile(mod, context, excludeFilePath) {
1370
+ if (!mod || mod.startsWith('.'))
1371
+ return null; // relative imports handled elsewhere
1372
+ const rel = mod.replace(/\./g, '/');
1373
+ const lastSeg = mod.split('.').pop();
1374
+ const endsWith = (p, want) => p === want || p.endsWith('/' + want);
1375
+ const moduleFile = context
1376
+ .getNodesByName(`${lastSeg}.py`)
1377
+ .find((n) => n.kind === 'file' && n.filePath !== excludeFilePath && endsWith(n.filePath, `${rel}.py`));
1378
+ if (moduleFile)
1379
+ return moduleFile;
1380
+ const pkgFile = context
1381
+ .getNodesByName('__init__.py')
1382
+ .find((n) => n.kind === 'file' && n.filePath !== excludeFilePath && endsWith(n.filePath, `${rel}/__init__.py`));
1383
+ return pkgFile ?? null;
1384
+ }
1385
+ /**
1386
+ * Resolve a Python ABSOLUTE dotted module import (`import a.b.c`) to its file —
1387
+ * the Django `AppConfig.ready(): import myapp.signals` pattern and any
1388
+ * side-effect module import.
1389
+ */
1390
+ function resolvePythonAbsoluteModule(ref, context) {
1391
+ if (ref.referenceKind !== 'imports')
1392
+ return null;
1393
+ // Only a DOTTED `import a.b.c` ref carries its full module path. A bare leaf
1394
+ // (`from app.api.routes import authentication`) is ambiguous on its own — three
1395
+ // `authentication.py` files may exist — so leave it to resolveModuleImportToFile,
1396
+ // which uses the import's source (`app.api.routes`) to build the full path.
1397
+ if (!ref.referenceName.includes('.'))
1398
+ return null;
1399
+ const hit = findPythonModuleFile(ref.referenceName, context, ref.filePath);
1400
+ return hit ? { original: ref, targetNodeId: hit.id, confidence: 0.9, resolvedBy: 'import' } : null;
1401
+ }
1402
+ /**
1403
+ * Resolve a Rust qualified reference `A::B::C` by mapping the MODULE prefix
1404
+ * (`A::B`) to a file and finding the leaf symbol (`C`) in it. This is the Rust
1405
+ * analog of {@link resolvePythonModuleMember} / {@link resolveGoCrossPackageReference}
1406
+ * and the precise answer to common-name re-exports (`pub use self::read::read`)
1407
+ * that name-matching can't disambiguate. Returns null when the prefix isn't a
1408
+ * real module path (e.g. `Widget::new` — `Widget` is a struct, not a module),
1409
+ * so associated-function calls and enum-variant paths fall through untouched.
1410
+ */
1411
+ function resolveRustPathReference(ref, context) {
1412
+ const segments = ref.referenceName.split('::').filter((s) => s.length > 0);
1413
+ if (segments.length < 2)
1414
+ return null;
1415
+ const leaf = segments[segments.length - 1];
1416
+ const modSegs = segments.slice(0, -1);
1417
+ const file = resolveRustModuleFile(modSegs, ref.filePath, context);
1418
+ if (!file || file === ref.filePath)
1419
+ return null;
1420
+ const target = context.getNodesInFile(file).find((n) => n.name === leaf &&
1421
+ (n.kind === 'function' ||
1422
+ n.kind === 'struct' ||
1423
+ n.kind === 'enum' ||
1424
+ n.kind === 'trait' ||
1425
+ n.kind === 'type_alias' ||
1426
+ n.kind === 'constant' ||
1427
+ n.kind === 'method' ||
1428
+ n.kind === 'class' ||
1429
+ n.kind === 'interface'));
1430
+ if (target) {
1431
+ return { original: ref, targetNodeId: target.id, confidence: 0.9, resolvedBy: 'import' };
1432
+ }
1433
+ return null;
1434
+ }
1435
+ /** The crate-root directory (holds `lib.rs`/`main.rs`), walking up from a file. */
1436
+ function rustCrateRootDir(fromFileAbs, context) {
1437
+ const projectRoot = context.getProjectRoot();
1438
+ const toRel = (p) => path.relative(projectRoot, p).replace(/\\/g, '/');
1439
+ let dir = path.dirname(fromFileAbs);
1440
+ for (let i = 0; i < 64; i++) {
1441
+ if (context.fileExists(toRel(path.join(dir, 'lib.rs'))) ||
1442
+ context.fileExists(toRel(path.join(dir, 'main.rs')))) {
1443
+ return dir;
1444
+ }
1445
+ const parent = path.dirname(dir);
1446
+ if (parent === dir)
1447
+ return null;
1448
+ dir = parent;
1449
+ }
1450
+ return null;
1451
+ }
1452
+ /** Directory under which the current file's module declares its SUBMODULES. */
1453
+ function rustSelfModuleDir(fromFileAbs) {
1454
+ const base = path.basename(fromFileAbs);
1455
+ const dir = path.dirname(fromFileAbs);
1456
+ // mod.rs / lib.rs / main.rs own their directory; `foo.rs`'s submodules live in `foo/`.
1457
+ if (base === 'mod.rs' || base === 'lib.rs' || base === 'main.rs')
1458
+ return dir;
1459
+ return path.join(dir, base.replace(/\.rs$/, ''));
1460
+ }
1461
+ /**
1462
+ * Resolve a Rust module path (segments WITHOUT the leaf symbol) to the file of
1463
+ * the last module segment — `crate::a::b` → `<crate>/a/b.rs` (or `.../b/mod.rs`).
1464
+ * Anchors on `crate` / `self` / `super`; a bare path is tried crate-relative.
1465
+ */
1466
+ function resolveRustModuleFile(segments, fromFile, context) {
1467
+ if (segments.length === 0)
1468
+ return null;
1469
+ const projectRoot = context.getProjectRoot();
1470
+ const fromAbs = path.join(projectRoot, fromFile);
1471
+ const toRel = (p) => path.relative(projectRoot, p).replace(/\\/g, '/');
1472
+ // Walk a sequence of module segments down from `startDir`, mapping each to a
1473
+ // `<seg>.rs` or `<seg>/mod.rs` file. Returns the leaf module's file, or null
1474
+ // if `startDir` is null or any segment has no file on disk.
1475
+ const resolveUnder = (startDir, rest) => {
1476
+ if (!startDir)
1477
+ return null;
1478
+ let dir = startDir;
1479
+ let targetFile = null;
1480
+ for (const seg of rest) {
1481
+ if (seg === 'self' || seg === 'crate' || seg === 'super')
1482
+ continue;
1483
+ const asFile = toRel(path.join(dir, seg + '.rs'));
1484
+ const asMod = toRel(path.join(dir, seg, 'mod.rs'));
1485
+ if (context.fileExists(asFile))
1486
+ targetFile = asFile;
1487
+ else if (context.fileExists(asMod))
1488
+ targetFile = asMod;
1489
+ else
1490
+ return null;
1491
+ dir = path.join(dir, seg);
1492
+ }
1493
+ return targetFile;
1494
+ };
1495
+ const first = segments[0];
1496
+ if (first === 'crate') {
1497
+ return resolveUnder(rustCrateRootDir(fromAbs, context), segments.slice(1));
1498
+ }
1499
+ if (first === 'self') {
1500
+ return resolveUnder(rustSelfModuleDir(fromAbs), segments.slice(1));
1501
+ }
1502
+ if (first === 'super') {
1503
+ let supers = 0;
1504
+ while (segments[supers] === 'super')
1505
+ supers++;
1506
+ let dir = rustSelfModuleDir(fromAbs);
1507
+ for (let s = 0; s < supers && dir; s++)
1508
+ dir = path.dirname(dir);
1509
+ return resolveUnder(dir, segments.slice(supers));
1510
+ }
1511
+ // Bare path. In expression position (`submodule::item()` — the router-assembly
1512
+ // and general cross-module-call pattern) the prefix is a SUBMODULE of the
1513
+ // current module, i.e. 2018 `self::`-relative — so try self-relative FIRST.
1514
+ // Fall back to crate-relative for 2015-edition / crate-root items. External
1515
+ // crate paths (`serde::de::Error`) miss both and fall through to name-matching.
1516
+ return (resolveUnder(rustSelfModuleDir(fromAbs), segments) ??
1517
+ resolveUnder(rustCrateRootDir(fromAbs, context), segments));
1518
+ }
1519
+ /**
1520
+ * Resolve a Java/Kotlin reference whose receiver is the simple name of
1521
+ * an imported FQN: `Foo.bar(...)` where `import com.example.Foo;`. The
1522
+ * imported FQN converts to a file-path suffix (`com/example/Foo.java`
1523
+ * or `.kt`) which uniquely identifies the right symbol when multiple
1524
+ * classes share the same simple name.
1525
+ *
1526
+ * Also handles bare references to the imported class itself
1527
+ * (`new Foo()` extraction emits `Foo` as a `references`/`instantiates`
1528
+ * ref) and `import static <Foo>.bar` style imports of a single member.
1529
+ */
1530
+ function resolveJavaImportedReference(ref, imports, context) {
1531
+ if (imports.length === 0)
1532
+ return null;
1533
+ const ext = ref.language === 'kotlin' ? '.kt' : '.java';
1534
+ for (const imp of imports) {
1535
+ const matchesBare = imp.localName === ref.referenceName;
1536
+ const matchesQualified = ref.referenceName.startsWith(imp.localName + '.');
1537
+ if (!matchesBare && !matchesQualified)
1538
+ continue;
1539
+ // Convert FQN to a file-path suffix. `com.example.Foo` ->
1540
+ // `com/example/Foo.java` (or `.kt`). The actual file may live
1541
+ // under any source root (`src/main/java/`, `src/`, etc.), so match
1542
+ // by suffix rather than exact path.
1543
+ const fqnPath = imp.source.replace(/\./g, '/') + ext;
1544
+ // Which symbol name to look up: the class itself, or a member.
1545
+ const memberName = matchesBare
1546
+ ? imp.localName
1547
+ : ref.referenceName.substring(imp.localName.length + 1);
1548
+ const candidates = context.getNodesByName(memberName);
1549
+ for (const node of candidates) {
1550
+ if (node.language !== ref.language)
1551
+ continue;
1552
+ const fp = node.filePath.replace(/\\/g, '/');
1553
+ if (fp.endsWith(fqnPath) || fp.endsWith('/' + fqnPath)) {
1554
+ return {
1555
+ original: ref,
1556
+ targetNodeId: node.id,
1557
+ confidence: 0.9,
1558
+ resolvedBy: 'import',
1559
+ };
1560
+ }
1561
+ }
1562
+ // `import static com.example.Foo.bar;` — the FQN's tail is the
1563
+ // member name, the part before is the owner class. Look up the
1564
+ // member named `<imp.localName>` (e.g. `bar`) and prefer the
1565
+ // candidate whose file matches the parent FQN's path.
1566
+ if (matchesBare) {
1567
+ const dot = imp.source.lastIndexOf('.');
1568
+ if (dot > 0) {
1569
+ const ownerFqn = imp.source.substring(0, dot);
1570
+ const ownerPath = ownerFqn.replace(/\./g, '/') + ext;
1571
+ for (const node of candidates) {
1572
+ if (node.language !== ref.language)
1573
+ continue;
1574
+ const fp = node.filePath.replace(/\\/g, '/');
1575
+ if (fp.endsWith(ownerPath) || fp.endsWith('/' + ownerPath)) {
1576
+ return {
1577
+ original: ref,
1578
+ targetNodeId: node.id,
1579
+ confidence: 0.9,
1580
+ resolvedBy: 'import',
1581
+ };
1582
+ }
1583
+ }
1584
+ }
1585
+ }
1586
+ }
1587
+ return null;
1588
+ }
1589
+ /**
1590
+ * Resolve a Go cross-package qualified reference (`pkga.FuncX`) by matching
1591
+ * the package alias against an in-module import, stripping the module prefix
1592
+ * to a project-relative directory, and locating the exported symbol in any
1593
+ * `.go` file under that directory. Returns `null` for stdlib / third-party
1594
+ * imports (no `go.mod`-relative match) so the rest of `resolveViaImport`
1595
+ * can still try the file-based path.
1596
+ */
1597
+ function resolveGoCrossPackageReference(ref, imports, context) {
1598
+ const mod = context.getGoModule?.();
1599
+ if (!mod)
1600
+ return null;
1601
+ // Qualified call: receiver before `.`, member after. A bare reference
1602
+ // (no dot) is a same-file/in-package call — handled elsewhere.
1603
+ const dotIdx = ref.referenceName.indexOf('.');
1604
+ if (dotIdx <= 0)
1605
+ return null;
1606
+ const receiver = ref.referenceName.substring(0, dotIdx);
1607
+ const memberName = ref.referenceName.substring(dotIdx + 1);
1608
+ if (!memberName)
1609
+ return null;
1610
+ for (const imp of imports) {
1611
+ if (imp.localName !== receiver)
1612
+ continue;
1613
+ // Only in-module imports map to a known directory.
1614
+ if (imp.source !== mod.modulePath && !imp.source.startsWith(mod.modulePath + '/')) {
1615
+ continue;
1616
+ }
1617
+ const pkgDir = imp.source === mod.modulePath
1618
+ ? ''
1619
+ : imp.source.substring(mod.modulePath.length + 1);
1620
+ // Look up the member by name and pick the candidate whose file lives
1621
+ // directly in the package directory. Match the immediate parent dir
1622
+ // exactly so a call to `pkga.FuncX` doesn't accidentally land on a
1623
+ // `FuncX` declared in `pkga/subpkg/`.
1624
+ const candidates = context.getNodesByName(memberName);
1625
+ for (const node of candidates) {
1626
+ if (node.language !== 'go')
1627
+ continue;
1628
+ if (!node.isExported)
1629
+ continue;
1630
+ const fp = node.filePath.replace(/\\/g, '/');
1631
+ const lastSlash = fp.lastIndexOf('/');
1632
+ const fileDir = lastSlash >= 0 ? fp.substring(0, lastSlash) : '';
1633
+ if (fileDir === pkgDir) {
1634
+ return {
1635
+ original: ref,
1636
+ targetNodeId: node.id,
1637
+ confidence: 0.9,
1638
+ resolvedBy: 'import',
1639
+ };
1640
+ }
1641
+ }
1642
+ }
1643
+ return null;
1644
+ }
1645
+ /** Recursive depth cap for re-export chain following. Real codebases
1646
+ * rarely chain barrels more than 2–3 deep; 8 is a generous safety
1647
+ * net that still bounds worst-case work. */
1648
+ const REEXPORT_MAX_DEPTH = 8;
1649
+ /**
1650
+ * Find an exported symbol in `filePath`, following `export { x } from
1651
+ * './other'` and `export * from './other'` chains until the original
1652
+ * declaration is reached. Cycle-safe via the `visited` set.
1653
+ *
1654
+ * Without this, every barrel-style import (`import { Foo } from
1655
+ * './index'` where `index.ts` only re-exports) used to resolve to
1656
+ * nothing — the existing code only looked for declarations IN the
1657
+ * resolved file, not declarations the file forwarded.
1658
+ */
1659
+ function findExportedSymbol(filePath, want, language, context, visited, depth = 0) {
1660
+ if (depth > REEXPORT_MAX_DEPTH)
1661
+ return undefined;
1662
+ if (visited.has(filePath))
1663
+ return undefined;
1664
+ visited.add(filePath);
1665
+ const nodesInFile = context.getNodesInFile(filePath);
1666
+ // 1. Direct hit: the symbol is declared in this file.
1667
+ if (want.isDefault) {
1668
+ // Svelte/Vue single-file components ARE the module's default export,
1669
+ // but are extracted as kind 'component' (not function/class). Prefer
1670
+ // the component node; fall back to an exported function/class for the
1671
+ // `.ts`/`.tsx` `export default fn`/`class` case. Without the component
1672
+ // branch, an `export { default as X } from './X.svelte'` barrel never
1673
+ // resolves and the component shows a false 0 callers (#629).
1674
+ const direct = nodesInFile.find((n) => n.isExported && n.kind === 'component') ??
1675
+ nodesInFile.find((n) => n.isExported && (n.kind === 'function' || n.kind === 'class'));
1676
+ if (direct)
1677
+ return direct;
1678
+ }
1679
+ else if (want.isNamespace && want.memberName) {
1680
+ const direct = nodesInFile.find((n) => n.name === want.memberName && n.isExported);
1681
+ if (direct)
1682
+ return direct;
1683
+ }
1684
+ else {
1685
+ const direct = nodesInFile.find((n) => n.name === want.exportedName && n.isExported);
1686
+ if (direct)
1687
+ return direct;
1688
+ }
1689
+ // 2. Re-export hit: the file forwards the symbol to another module.
1690
+ const reExports = context.getReExports?.(filePath, language) ?? [];
1691
+ if (reExports.length === 0)
1692
+ return undefined;
1693
+ // Look for explicit `export { want } from './other'` (with optional rename).
1694
+ const targetName = want.isDefault ? 'default' : want.exportedName;
1695
+ for (const rex of reExports) {
1696
+ if (rex.kind === 'named' && rex.exportedName === targetName) {
1697
+ const next = resolveImportPath(rex.source, filePath, language, context);
1698
+ if (!next)
1699
+ continue;
1700
+ // After rename: `export { foo as bar } from './x'` — to chase
1701
+ // `bar`, we look for `foo` in `./x`.
1702
+ const chained = findExportedSymbol(next, {
1703
+ isDefault: rex.originalName === 'default',
1704
+ isNamespace: false,
1705
+ exportedName: rex.originalName,
1706
+ memberName: null,
1707
+ }, language, context, visited, depth + 1);
1708
+ if (chained)
1709
+ return chained;
1710
+ }
1711
+ }
1712
+ // 3. Wildcard re-export: `export * from './other'` — try every
1713
+ // forwarding source. This is the barrel-of-barrels case.
1714
+ for (const rex of reExports) {
1715
+ if (rex.kind === 'wildcard') {
1716
+ const next = resolveImportPath(rex.source, filePath, language, context);
1717
+ if (!next)
1718
+ continue;
1719
+ const chained = findExportedSymbol(next, want, language, context, visited, depth + 1);
1720
+ if (chained)
1721
+ return chained;
1722
+ }
1723
+ }
1724
+ return undefined;
1725
+ }
1726
+ //# sourceMappingURL=import-resolver.js.map