@nanonets/graft 0.13.0 → 0.16.0

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 (308) hide show
  1. package/README.md +26 -10
  2. package/dist/ai/crux.d.ts +14 -1
  3. package/dist/ai/crux.d.ts.map +1 -1
  4. package/dist/ai/crux.js +39 -51
  5. package/dist/ai/crux.js.map +1 -1
  6. package/dist/ai/failure.d.ts +13 -2
  7. package/dist/ai/failure.d.ts.map +1 -1
  8. package/dist/ai/failure.js +16 -4
  9. package/dist/ai/failure.js.map +1 -1
  10. package/dist/ai/llm/factory.d.ts +10 -1
  11. package/dist/ai/llm/factory.d.ts.map +1 -1
  12. package/dist/ai/llm/factory.js +16 -0
  13. package/dist/ai/llm/factory.js.map +1 -1
  14. package/dist/ai/llm/litellm.d.ts +34 -0
  15. package/dist/ai/llm/litellm.d.ts.map +1 -0
  16. package/dist/ai/llm/litellm.js +45 -0
  17. package/dist/ai/llm/litellm.js.map +1 -0
  18. package/dist/ai/llm/openai.d.ts.map +1 -1
  19. package/dist/ai/llm/openai.js +66 -7
  20. package/dist/ai/llm/openai.js.map +1 -1
  21. package/dist/ai/llm/orcarouter.d.ts +34 -0
  22. package/dist/ai/llm/orcarouter.d.ts.map +1 -0
  23. package/dist/ai/llm/orcarouter.js +45 -0
  24. package/dist/ai/llm/orcarouter.js.map +1 -0
  25. package/dist/ai/llm/recover-tool.d.ts +19 -0
  26. package/dist/ai/llm/recover-tool.d.ts.map +1 -0
  27. package/dist/ai/llm/recover-tool.js +109 -0
  28. package/dist/ai/llm/recover-tool.js.map +1 -0
  29. package/dist/ai/providers.d.ts.map +1 -1
  30. package/dist/ai/providers.js +15 -3
  31. package/dist/ai/providers.js.map +1 -1
  32. package/dist/ai/synthesize.d.ts.map +1 -1
  33. package/dist/ai/synthesize.js +19 -5
  34. package/dist/ai/synthesize.js.map +1 -1
  35. package/dist/app/checkout.d.ts +28 -0
  36. package/dist/app/checkout.d.ts.map +1 -0
  37. package/dist/app/checkout.js +100 -0
  38. package/dist/app/checkout.js.map +1 -0
  39. package/dist/app/events.d.ts +37 -0
  40. package/dist/app/events.d.ts.map +1 -0
  41. package/dist/app/events.js +59 -0
  42. package/dist/app/events.js.map +1 -0
  43. package/dist/app/identity.d.ts +54 -0
  44. package/dist/app/identity.d.ts.map +1 -0
  45. package/dist/app/identity.js +96 -0
  46. package/dist/app/identity.js.map +1 -0
  47. package/dist/app/main.d.ts +2 -0
  48. package/dist/app/main.d.ts.map +1 -0
  49. package/dist/app/main.js +56 -0
  50. package/dist/app/main.js.map +1 -0
  51. package/dist/app/pages.d.ts +39 -0
  52. package/dist/app/pages.d.ts.map +1 -0
  53. package/dist/app/pages.js +86 -0
  54. package/dist/app/pages.js.map +1 -0
  55. package/dist/app/queue.d.ts +40 -0
  56. package/dist/app/queue.d.ts.map +1 -0
  57. package/dist/app/queue.js +68 -0
  58. package/dist/app/queue.js.map +1 -0
  59. package/dist/app/review.d.ts +23 -0
  60. package/dist/app/review.d.ts.map +1 -0
  61. package/dist/app/review.js +139 -0
  62. package/dist/app/review.js.map +1 -0
  63. package/dist/app/server.d.ts +40 -0
  64. package/dist/app/server.d.ts.map +1 -0
  65. package/dist/app/server.js +117 -0
  66. package/dist/app/server.js.map +1 -0
  67. package/dist/ask/ask.d.ts +35 -0
  68. package/dist/ask/ask.d.ts.map +1 -1
  69. package/dist/ask/ask.js +427 -63
  70. package/dist/ask/ask.js.map +1 -1
  71. package/dist/ask/file-rank.d.ts +72 -0
  72. package/dist/ask/file-rank.d.ts.map +1 -0
  73. package/dist/ask/file-rank.js +160 -0
  74. package/dist/ask/file-rank.js.map +1 -0
  75. package/dist/ask/file-selection.d.ts +4 -0
  76. package/dist/ask/file-selection.d.ts.map +1 -1
  77. package/dist/ask/file-selection.js +25 -0
  78. package/dist/ask/file-selection.js.map +1 -1
  79. package/dist/ask/fuse.d.ts +16 -0
  80. package/dist/ask/fuse.d.ts.map +1 -1
  81. package/dist/ask/fuse.js +21 -4
  82. package/dist/ask/fuse.js.map +1 -1
  83. package/dist/ask/graphrank.d.ts +18 -0
  84. package/dist/ask/graphrank.d.ts.map +1 -1
  85. package/dist/ask/graphrank.js +65 -19
  86. package/dist/ask/graphrank.js.map +1 -1
  87. package/dist/blast/blast-cli.d.ts +5 -0
  88. package/dist/blast/blast-cli.d.ts.map +1 -1
  89. package/dist/blast/blast-cli.js +21 -30
  90. package/dist/blast/blast-cli.js.map +1 -1
  91. package/dist/blast/blast.d.ts +9 -0
  92. package/dist/blast/blast.d.ts.map +1 -1
  93. package/dist/blast/blast.js.map +1 -1
  94. package/dist/blast/name.d.ts +13 -0
  95. package/dist/blast/name.d.ts.map +1 -1
  96. package/dist/blast/name.js +36 -0
  97. package/dist/blast/name.js.map +1 -1
  98. package/dist/blast/owners.d.ts +85 -0
  99. package/dist/blast/owners.d.ts.map +1 -0
  100. package/dist/blast/owners.js +272 -0
  101. package/dist/blast/owners.js.map +1 -0
  102. package/dist/blast/render.d.ts.map +1 -1
  103. package/dist/blast/render.js +105 -0
  104. package/dist/blast/render.js.map +1 -1
  105. package/dist/blast/viz.d.ts.map +1 -1
  106. package/dist/blast/viz.js +10 -0
  107. package/dist/blast/viz.js.map +1 -1
  108. package/dist/claude/format.js +1 -1
  109. package/dist/claude/format.js.map +1 -1
  110. package/dist/claude/hooks.d.ts.map +1 -1
  111. package/dist/claude/hooks.js +132 -22
  112. package/dist/claude/hooks.js.map +1 -1
  113. package/dist/claude/init.d.ts +1 -0
  114. package/dist/claude/init.d.ts.map +1 -1
  115. package/dist/claude/init.js +1 -1
  116. package/dist/claude/init.js.map +1 -1
  117. package/dist/claude/session-metrics.d.ts +63 -0
  118. package/dist/claude/session-metrics.d.ts.map +1 -0
  119. package/dist/claude/session-metrics.js +181 -0
  120. package/dist/claude/session-metrics.js.map +1 -0
  121. package/dist/claude/settings-merge.d.ts +18 -1
  122. package/dist/claude/settings-merge.d.ts.map +1 -1
  123. package/dist/claude/settings-merge.js +70 -27
  124. package/dist/claude/settings-merge.js.map +1 -1
  125. package/dist/claude/state.d.ts +25 -0
  126. package/dist/claude/state.d.ts.map +1 -1
  127. package/dist/claude/state.js +14 -1
  128. package/dist/claude/state.js.map +1 -1
  129. package/dist/claude/statusline.d.ts +5 -3
  130. package/dist/claude/statusline.d.ts.map +1 -1
  131. package/dist/claude/statusline.js +6 -4
  132. package/dist/claude/statusline.js.map +1 -1
  133. package/dist/claude/tally.d.ts +23 -0
  134. package/dist/claude/tally.d.ts.map +1 -0
  135. package/dist/claude/tally.js +138 -0
  136. package/dist/claude/tally.js.map +1 -0
  137. package/dist/cli.js +145 -4
  138. package/dist/cli.js.map +1 -1
  139. package/dist/context/build.d.ts +11 -0
  140. package/dist/context/build.d.ts.map +1 -1
  141. package/dist/context/build.js +49 -9
  142. package/dist/context/build.js.map +1 -1
  143. package/dist/context/check.d.ts.map +1 -1
  144. package/dist/context/check.js +5 -12
  145. package/dist/context/check.js.map +1 -1
  146. package/dist/context/node-file.d.ts +2 -1
  147. package/dist/context/node-file.d.ts.map +1 -1
  148. package/dist/context/node-file.js +70 -3
  149. package/dist/context/node-file.js.map +1 -1
  150. package/dist/context/savings.d.ts +8 -0
  151. package/dist/context/savings.d.ts.map +1 -1
  152. package/dist/context/savings.js +14 -0
  153. package/dist/context/savings.js.map +1 -1
  154. package/dist/engine.d.ts +4 -0
  155. package/dist/engine.d.ts.map +1 -1
  156. package/dist/engine.js +2 -0
  157. package/dist/engine.js.map +1 -1
  158. package/dist/graph/bindings.d.ts +6 -5
  159. package/dist/graph/bindings.d.ts.map +1 -1
  160. package/dist/graph/bindings.js +117 -5
  161. package/dist/graph/bindings.js.map +1 -1
  162. package/dist/graph/build.d.ts +4 -0
  163. package/dist/graph/build.d.ts.map +1 -1
  164. package/dist/graph/build.js +7 -4
  165. package/dist/graph/build.js.map +1 -1
  166. package/dist/graph/cards.d.ts +4 -3
  167. package/dist/graph/cards.d.ts.map +1 -1
  168. package/dist/graph/cards.js +34 -6
  169. package/dist/graph/cards.js.map +1 -1
  170. package/dist/graph/check.d.ts.map +1 -1
  171. package/dist/graph/check.js +36 -6
  172. package/dist/graph/check.js.map +1 -1
  173. package/dist/graph/enrich.d.ts +4 -4
  174. package/dist/graph/enrich.d.ts.map +1 -1
  175. package/dist/graph/enrich.js +32 -6
  176. package/dist/graph/enrich.js.map +1 -1
  177. package/dist/graph/extract.d.ts +9 -2
  178. package/dist/graph/extract.d.ts.map +1 -1
  179. package/dist/graph/extract.js +356 -12
  180. package/dist/graph/extract.js.map +1 -1
  181. package/dist/graph/fingerprint.d.ts +6 -1
  182. package/dist/graph/fingerprint.d.ts.map +1 -1
  183. package/dist/graph/fingerprint.js +7 -3
  184. package/dist/graph/fingerprint.js.map +1 -1
  185. package/dist/graph/generic.d.ts +10 -0
  186. package/dist/graph/generic.d.ts.map +1 -1
  187. package/dist/graph/generic.js +20 -3
  188. package/dist/graph/generic.js.map +1 -1
  189. package/dist/graph/invariants.d.ts +3 -2
  190. package/dist/graph/invariants.d.ts.map +1 -1
  191. package/dist/graph/invariants.js +6 -3
  192. package/dist/graph/invariants.js.map +1 -1
  193. package/dist/graph/refresh.d.ts.map +1 -1
  194. package/dist/graph/refresh.js +6 -2
  195. package/dist/graph/refresh.js.map +1 -1
  196. package/dist/graph/resolve.d.ts +1 -1
  197. package/dist/graph/resolve.d.ts.map +1 -1
  198. package/dist/graph/resolve.js +106 -5
  199. package/dist/graph/resolve.js.map +1 -1
  200. package/dist/graph/scopes.d.ts.map +1 -1
  201. package/dist/graph/scopes.js +2 -1
  202. package/dist/graph/scopes.js.map +1 -1
  203. package/dist/graph/source-files.d.ts +7 -2
  204. package/dist/graph/source-files.d.ts.map +1 -1
  205. package/dist/graph/source-files.js +19 -6
  206. package/dist/graph/source-files.js.map +1 -1
  207. package/dist/graph/workspace-cli.d.ts +2 -0
  208. package/dist/graph/workspace-cli.d.ts.map +1 -1
  209. package/dist/graph/workspace-cli.js +3 -0
  210. package/dist/graph/workspace-cli.js.map +1 -1
  211. package/dist/graph/workspace.d.ts +2 -0
  212. package/dist/graph/workspace.d.ts.map +1 -1
  213. package/dist/graph/workspace.js +173 -6
  214. package/dist/graph/workspace.js.map +1 -1
  215. package/dist/hosts/antigravity.d.ts +2 -2
  216. package/dist/hosts/antigravity.d.ts.map +1 -1
  217. package/dist/hosts/codex-hooks.d.ts +2 -6
  218. package/dist/hosts/codex-hooks.d.ts.map +1 -1
  219. package/dist/hosts/codex-hooks.js +7 -30
  220. package/dist/hosts/codex-hooks.js.map +1 -1
  221. package/dist/hosts/config-write.d.ts +36 -0
  222. package/dist/hosts/config-write.d.ts.map +1 -0
  223. package/dist/hosts/config-write.js +63 -0
  224. package/dist/hosts/config-write.js.map +1 -0
  225. package/dist/hosts/cursor-hooks.d.ts +18 -0
  226. package/dist/hosts/cursor-hooks.d.ts.map +1 -0
  227. package/dist/hosts/cursor-hooks.js +100 -0
  228. package/dist/hosts/cursor-hooks.js.map +1 -0
  229. package/dist/hosts/init.d.ts +2 -2
  230. package/dist/hosts/init.d.ts.map +1 -1
  231. package/dist/hosts/init.js +8 -2
  232. package/dist/hosts/init.js.map +1 -1
  233. package/dist/hosts/mcp-config.d.ts +15 -5
  234. package/dist/hosts/mcp-config.d.ts.map +1 -1
  235. package/dist/hosts/mcp-config.js +51 -15
  236. package/dist/hosts/mcp-config.js.map +1 -1
  237. package/dist/hosts/plan.d.ts.map +1 -1
  238. package/dist/hosts/plan.js +2 -0
  239. package/dist/hosts/plan.js.map +1 -1
  240. package/dist/hosts/retract.d.ts +47 -0
  241. package/dist/hosts/retract.d.ts.map +1 -0
  242. package/dist/hosts/retract.js +473 -0
  243. package/dist/hosts/retract.js.map +1 -0
  244. package/dist/index.d.ts +2 -0
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +2 -0
  247. package/dist/index.js.map +1 -1
  248. package/dist/ingest/fs.d.ts +39 -5
  249. package/dist/ingest/fs.d.ts.map +1 -1
  250. package/dist/ingest/fs.js +104 -11
  251. package/dist/ingest/fs.js.map +1 -1
  252. package/dist/mcp/tool-names.d.ts +20 -0
  253. package/dist/mcp/tool-names.d.ts.map +1 -0
  254. package/dist/mcp/tool-names.js +36 -0
  255. package/dist/mcp/tool-names.js.map +1 -0
  256. package/dist/mcp/tools.d.ts +11 -2
  257. package/dist/mcp/tools.d.ts.map +1 -1
  258. package/dist/mcp/tools.js +9 -21
  259. package/dist/mcp/tools.js.map +1 -1
  260. package/dist/telemetry/contract.d.ts.map +1 -1
  261. package/dist/telemetry/contract.js +17 -3
  262. package/dist/telemetry/contract.js.map +1 -1
  263. package/dist/telemetry/flush.d.ts.map +1 -1
  264. package/dist/telemetry/flush.js +1 -0
  265. package/dist/telemetry/flush.js.map +1 -1
  266. package/dist/telemetry/identity.d.ts +7 -0
  267. package/dist/telemetry/identity.d.ts.map +1 -1
  268. package/dist/telemetry/identity.js.map +1 -1
  269. package/dist/telemetry/index.d.ts +2 -2
  270. package/dist/telemetry/index.d.ts.map +1 -1
  271. package/dist/telemetry/index.js +2 -2
  272. package/dist/telemetry/index.js.map +1 -1
  273. package/dist/telemetry/sessions.d.ts +19 -2
  274. package/dist/telemetry/sessions.d.ts.map +1 -1
  275. package/dist/telemetry/sessions.js +57 -34
  276. package/dist/telemetry/sessions.js.map +1 -1
  277. package/dist/telemetry/track.d.ts +22 -3
  278. package/dist/telemetry/track.d.ts.map +1 -1
  279. package/dist/telemetry/track.js +34 -5
  280. package/dist/telemetry/track.js.map +1 -1
  281. package/dist/upkeep-run.js +1 -1
  282. package/dist/upkeep-run.js.map +1 -1
  283. package/dist/upkeep.d.ts +7 -4
  284. package/dist/upkeep.d.ts.map +1 -1
  285. package/dist/upkeep.js +2 -1
  286. package/dist/upkeep.js.map +1 -1
  287. package/dist/util/state.d.ts +12 -2
  288. package/dist/util/state.d.ts.map +1 -1
  289. package/dist/util/state.js +4 -0
  290. package/dist/util/state.js.map +1 -1
  291. package/dist/viewer/app.js +2 -1
  292. package/dist/viewer/style.css +14 -0
  293. package/dist/viz/assemble.d.ts +17 -0
  294. package/dist/viz/assemble.d.ts.map +1 -1
  295. package/dist/viz/assemble.js.map +1 -1
  296. package/package.json +12 -4
  297. package/scripts/graph-quality.mjs +3 -3
  298. package/scripts/postinstall.mjs +42 -3
  299. package/scripts/run-tests.mjs +14 -0
  300. package/scripts/tally-audit.mjs +140 -0
  301. package/dist/ai/llm/claude-cli.d.ts +0 -60
  302. package/dist/ai/llm/claude-cli.d.ts.map +0 -1
  303. package/dist/ai/llm/claude-cli.js +0 -417
  304. package/dist/ai/llm/claude-cli.js.map +0 -1
  305. package/dist/util/num.d.ts +0 -3
  306. package/dist/util/num.d.ts.map +0 -1
  307. package/dist/util/num.js +0 -20
  308. package/dist/util/num.js.map +0 -1
@@ -13,6 +13,7 @@ import Go from "tree-sitter-go";
13
13
  import R from "tree-sitter-r";
14
14
  import Java from "tree-sitter-java";
15
15
  import Kotlin from "tree-sitter-kotlin";
16
+ import Swift from "tree-sitter-swift";
16
17
  import PHP from "tree-sitter-php";
17
18
  import { basename } from "node:path";
18
19
  import { contentHash } from "../util/id.js";
@@ -47,6 +48,7 @@ const EXTENSIONS = [
47
48
  { ext: ".java", grammar: "java", label: "java" },
48
49
  { ext: ".kt", grammar: "kotlin", label: "kotlin" },
49
50
  { ext: ".kts", grammar: "kotlin", label: "kotlin" },
51
+ { ext: ".swift", grammar: "swift", label: "swift" },
50
52
  { ext: ".php", grammar: "php", label: "php" },
51
53
  // `entryFor` lower-cases the path before matching, so this one entry covers
52
54
  // both `.R` (the conventional case in real R codebases) and `.r`.
@@ -164,6 +166,29 @@ const KOTLIN_KINDS = {
164
166
  * "class" also covers object_declaration (it maps to "class"); interface/enum are the
165
167
  * same class_declaration node rekinded in describeKotlin, so all three land in the set. */
166
168
  const KOTLIN_TYPE_KINDS = new Set(["class", "interface", "enum"]);
169
+ const SWIFT_KINDS = {
170
+ class_declaration: "class", // → "struct" / "enum" in describeSwift (one node type covers all five keywords)
171
+ protocol_declaration: "interface",
172
+ function_declaration: "function", // → "method" inside a type (resolved in the walk)
173
+ protocol_function_declaration: "method", // a protocol requirement is always a member
174
+ init_declaration: "method", // the type's own initializer (named after it, like a Java constructor)
175
+ typealias_declaration: "type",
176
+ property_declaration: "variable", // top-level `let`/`var` only (fields resolved in the walk)
177
+ };
178
+ /** Swift type declarations: they set `enclosingClass` for the members nested in them.
179
+ * class/struct/enum are the same class_declaration node rekinded in describeSwift
180
+ * (an actor takes "class"); protocols are "interface". "module" is an extension
181
+ * body — a member-contributing scope named after the extended type, deliberately
182
+ * NOT a type kind in the graph so it can never make the real declaration's name
183
+ * ambiguous (see describeSwift's extension branch) — but its members still
184
+ * promote to methods owned by that type, which is why it belongs in this set. */
185
+ const SWIFT_TYPE_KINDS = new Set([
186
+ "class",
187
+ "struct",
188
+ "enum",
189
+ "interface",
190
+ "module",
191
+ ]);
167
192
  // PHP: definition node types are all distinct (no py-style function→method
168
193
  // promotion needed — a class body uses `method_declaration`, not
169
194
  // `function_definition`). `trait_declaration` maps to the PHP-only `trait` kind.
@@ -183,6 +208,7 @@ const KINDS_BY_LANG = {
183
208
  r: R_KINDS,
184
209
  java: JAVA_KINDS,
185
210
  kotlin: KOTLIN_KINDS,
211
+ swift: SWIFT_KINDS,
186
212
  php: PHP_KINDS,
187
213
  };
188
214
  /**
@@ -201,6 +227,7 @@ const CALL_TYPES = {
201
227
  go: new Set(["call_expression"]),
202
228
  java: new Set(["method_invocation", "object_creation_expression"]),
203
229
  kotlin: new Set(["call_expression"]),
230
+ swift: new Set(["call_expression"]),
204
231
  php: new Set([
205
232
  "function_call_expression",
206
233
  "member_call_expression",
@@ -225,6 +252,7 @@ const GRAMMARS = {
225
252
  r: R,
226
253
  java: Java,
227
254
  kotlin: Kotlin,
255
+ swift: Swift,
228
256
  php: PHP.php,
229
257
  };
230
258
  /** tree-sitter's string `parse()` fails with "Invalid argument" on any input
@@ -429,9 +457,11 @@ function walk(node, ctx, out, edges, minted) {
429
457
  ? javaExported(node)
430
458
  : ctx.lang === "kotlin"
431
459
  ? kotlinExported(node)
432
- : ctx.lang === "php"
433
- ? phpExported(node)
434
- : tsExported(node),
460
+ : ctx.lang === "swift"
461
+ ? swiftExported(node)
462
+ : ctx.lang === "php"
463
+ ? phpExported(node)
464
+ : tsExported(node),
435
465
  origin: "ast",
436
466
  body_hash: contentHash(desc.hashNode.text),
437
467
  body_text: searchBody(desc.hashNode.text),
@@ -448,11 +478,14 @@ function walk(node, ctx, out, edges, minted) {
448
478
  // may `implements`, so every type declaration is a heritage site, not just a class.
449
479
  const javaTypeDecl = ctx.lang === "java" && JAVA_TYPE_KINDS.has(desc.kind);
450
480
  const kotlinTypeDecl = ctx.lang === "kotlin" && KOTLIN_TYPE_KINDS.has(desc.kind);
451
- if (desc.kind === "class" || javaTypeDecl || kotlinTypeDecl)
481
+ const swiftTypeDecl = ctx.lang === "swift" && SWIFT_TYPE_KINDS.has(desc.kind);
482
+ if (desc.kind === "class" || javaTypeDecl || kotlinTypeDecl || swiftTypeDecl)
452
483
  edges.push(...heritageEdges(node, id, ctx));
453
484
  if (ctx.lang === "php")
454
485
  edges.push(...phpAttributeReferenceEdges(node, id, ctx));
455
- const enclosingClass = desc.kind === "class" || javaTypeDecl || kotlinTypeDecl
486
+ if (ctx.lang === "java")
487
+ edges.push(...javaAnnotationReferenceEdges(node, id, ctx));
488
+ const enclosingClass = desc.kind === "class" || javaTypeDecl || kotlinTypeDecl || swiftTypeDecl
456
489
  ? desc.name
457
490
  : isGoMethod
458
491
  ? goReceiverType(node)
@@ -474,9 +507,17 @@ function walk(node, ctx, out, edges, minted) {
474
507
  // defined inside one).
475
508
  rR6Access: null,
476
509
  // Unlike rR6Access, only reset when entering a genuinely new class (so it
477
- // stays live through a method's whole body, where super$ calls actually
478
- // happen) — inherited unchanged for every other definition kind.
479
- rSuperClass: desc.kind === "class" ? (ctx.lang === "r" ? rR6ParentClass(node) : null) : ctx.rSuperClass,
510
+ // stays live through a method's whole body, where super$ / super. calls
511
+ // actually happen) — inherited unchanged for every other definition kind.
512
+ // Swift reads it off the declaration's own `:` clause, so `super.ping()`
513
+ // resolves against the PARENT type, not the overriding current one.
514
+ rSuperClass: desc.kind === "class"
515
+ ? ctx.lang === "r"
516
+ ? rR6ParentClass(node)
517
+ : ctx.lang === "swift"
518
+ ? swiftSuperClassName(node)
519
+ : null
520
+ : ctx.rSuperClass,
480
521
  };
481
522
  walkNamedChildren(node.namedChildren, childCtx, out, edges, minted);
482
523
  return;
@@ -541,12 +582,44 @@ function walk(node, ctx, out, edges, minted) {
541
582
  file: ctx.rel,
542
583
  ...(callee.kinds ? { kinds: callee.kinds } : {}),
543
584
  };
544
- // Java only: the call site's argument count, to pick the right overload.
545
- const argCount = ctx.lang === "java" ? javaArgCount(node) : undefined;
585
+ // Overloading languages: the call site's argument count, to pick the right
586
+ // overload (see RawEdge.argCount).
587
+ const argCount = ctx.lang === "java" ? javaArgCount(node) : ctx.lang === "swift" ? swiftArgCount(node) : undefined;
546
588
  if (argCount !== undefined)
547
589
  callEdge.argCount = argCount;
548
- const recvType = resolveRecvType(callee.receiver, ctx);
549
- edges.push(recvType ? { ...callEdge, recvType } : callEdge);
590
+ // Swift: a bare lowercase call inside a type body may be an implicit-`self`
591
+ // member call (`walk()` for `self.walk()`), syntactically indistinguishable
592
+ // from a free-function call — and Swift's own lookup is member-FIRST (inner
593
+ // scope wins). So the edge is emitted as the member reading, typed to the
594
+ // enclosing class — resolved through the owner-qualified method index and
595
+ // the class's in-repo ancestor chain (`clearLogs()` in a test subclass
596
+ // finds the base class's method) — with `implicitSelf` letting resolve.ts
597
+ // fall back to the free-function reading only when no member exists on the
598
+ // chain. One edge, both readings, language-order precedence. This is
599
+ // deliberately NOT a bare-name kind widening: dogfooding on
600
+ // swift-composable-architecture, a global unique-name match bound
601
+ // `contains(element)` inside `extension Set` — a stdlib call — to an
602
+ // unrelated type's only in-repo `contains`. And not for an UpperCamelCase
603
+ // callee: that is an initializer call (`Text("hi")`), which takes
604
+ // resolve.ts's class/struct/enum fallback instead — extension nodes (kind
605
+ // "module") can never false-match it.
606
+ const swiftImplicitSelf = ctx.lang === "swift" &&
607
+ !callee.viaMember &&
608
+ !callee.kinds &&
609
+ ctx.enclosingClass &&
610
+ !/^[A-Z]/.test(callee.name);
611
+ if (swiftImplicitSelf) {
612
+ edges.push({
613
+ ...callEdge,
614
+ viaMember: true,
615
+ recvType: ctx.enclosingClass,
616
+ implicitSelf: true,
617
+ });
618
+ }
619
+ else {
620
+ const recvType = resolveRecvType(callee.receiver, ctx);
621
+ edges.push(recvType ? { ...callEdge, recvType } : callEdge);
622
+ }
550
623
  }
551
624
  }
552
625
  else if (ctx.lang === "php" && node.type === "use_declaration") {
@@ -750,6 +823,38 @@ function phpAttributeClassRef(attr, ctx) {
750
823
  return { name: imported.name, specifier: imported.specifier };
751
824
  return { name: bare };
752
825
  }
826
+ /** Java annotations on a definition → `references` edges to the annotation type. */
827
+ function javaAnnotationReferenceEdges(node, sourceId, ctx) {
828
+ const edges = [];
829
+ const mods = node.namedChildren.find((c) => c.type === "modifiers");
830
+ if (!mods)
831
+ return edges;
832
+ for (const child of mods.namedChildren) {
833
+ if (child.type !== "marker_annotation" && child.type !== "annotation")
834
+ continue;
835
+ const name = javaAnnotationTypeName(child);
836
+ if (name) {
837
+ edges.push({
838
+ source: sourceId,
839
+ relation: "references",
840
+ name,
841
+ file: ctx.rel,
842
+ });
843
+ }
844
+ }
845
+ return edges;
846
+ }
847
+ /** The type named by `@Foo` / `@a.b.Foo(...)`. Arguments are ignored (issue #89).
848
+ * A scoped name is kept whole, matching heritage: a bare last segment would
849
+ * false-match an unrelated in-repo type (#103). */
850
+ function javaAnnotationTypeName(anno) {
851
+ const nameNode = anno.childForFieldName("name");
852
+ if (!nameNode)
853
+ return null;
854
+ if (nameNode.type === "identifier" || nameNode.type === "scoped_identifier")
855
+ return nameNode.text;
856
+ return null;
857
+ }
753
858
  function collectTsImportBindings(node, specifier, out) {
754
859
  if (node.type === "import_specifier") {
755
860
  const name = node.childForFieldName("name")?.text;
@@ -846,6 +951,8 @@ function describe(node, ctx) {
846
951
  return describeJava(node, ctx);
847
952
  if (ctx.lang === "kotlin")
848
953
  return describeKotlin(node, ctx);
954
+ if (ctx.lang === "swift")
955
+ return describeSwift(node, ctx);
849
956
  // PHP closures: `$h = function () {…}` / `fn() => …`, and bare callbacks
850
957
  // (`$routes->get('/x', function () {…})`). Captured as function nodes so a
851
958
  // closure-only file (a routing table, a DI container) keeps its structure
@@ -1489,6 +1596,121 @@ function describeKotlin(node, ctx) {
1489
1596
  }
1490
1597
  return null;
1491
1598
  }
1599
+ /** Swift definition shapes. Like Kotlin's, tree-sitter-swift exposes no `name` or
1600
+ * `body` fields: a definition's name is a direct `type_identifier` (types) or
1601
+ * `simple_identifier` (functions) child, and its body is a `class_body` /
1602
+ * `enum_class_body` / `protocol_body` / `function_body` child. One
1603
+ * `class_declaration` node type covers `class`, `struct`, `enum`, `actor` AND
1604
+ * `extension` — the declaration's own keyword token tells them apart. */
1605
+ function describeSwift(node, ctx) {
1606
+ // The first direct `type_identifier` is the declared name (generic parameters and
1607
+ // inheritance specifiers are all nested beneath other child nodes).
1608
+ const typeName = () => node.namedChildren.find((c) => c.type === "type_identifier")?.text ?? null;
1609
+ // The first direct `simple_identifier` is the function name (parameters and
1610
+ // generic parameters are all nested beneath other child nodes).
1611
+ const funcName = () => node.namedChildren.find((c) => c.type === "simple_identifier")?.text ?? null;
1612
+ const headEnd = (...types) => {
1613
+ const body = node.namedChildren.find((c) => types.includes(c.type));
1614
+ return body ? body.startIndex : node.endIndex;
1615
+ };
1616
+ if (node.type === "class_declaration") {
1617
+ const kw = node.children.find((c) => c.type === "class" ||
1618
+ c.type === "struct" ||
1619
+ c.type === "enum" ||
1620
+ c.type === "actor" ||
1621
+ c.type === "extension")?.type;
1622
+ let name;
1623
+ if (kw === "extension") {
1624
+ // `extension Point { … }` has no name of its own — the extended type's IS its
1625
+ // identity, so the node takes that name: members mint as `Point.method`,
1626
+ // `enclosingClass` becomes `Point`, and a member call on a Point receiver
1627
+ // resolves to them exactly as if they were declared on the type. A qualified
1628
+ // target (`extension Swift.Array`) reduces to its last component, matching
1629
+ // how the extended type is itself named in the graph.
1630
+ //
1631
+ // Its KIND is "module", not "class": the type usually already has a real
1632
+ // declaration, and a second same-named "class" node would make the name
1633
+ // AMBIGUOUS to resolveName — every `Point(...)` initializer call and every
1634
+ // `: Point` heritage target would then drop instead of resolving (resolve
1635
+ // never guesses between same-named candidates). "module" keeps the node out
1636
+ // of type-name resolution entirely while SWIFT_TYPE_KINDS still makes it
1637
+ // own its members; typed member calls are untouched either way, since they
1638
+ // go through the owner-qualified method index, not the type's own node.
1639
+ const ut = node.namedChildren.find((c) => c.type === "user_type");
1640
+ const ids = ut?.namedChildren.filter((c) => c.type === "type_identifier") ?? [];
1641
+ name = ids.length ? ids[ids.length - 1].text : null;
1642
+ }
1643
+ else {
1644
+ name = typeName();
1645
+ }
1646
+ if (!name)
1647
+ return null;
1648
+ // An actor is class-like (reference semantics, methods) and there is no
1649
+ // dedicated actor kind, so it takes "class".
1650
+ const kind = kw === "extension" ? "module" : kw === "struct" ? "struct" : kw === "enum" ? "enum" : "class";
1651
+ return { name, kind, headerEnd: headEnd("class_body", "enum_class_body"), hashNode: node };
1652
+ }
1653
+ if (node.type === "protocol_declaration") {
1654
+ const name = typeName();
1655
+ if (!name)
1656
+ return null;
1657
+ return { name, kind: "interface", headerEnd: headEnd("protocol_body"), hashNode: node };
1658
+ }
1659
+ // A protocol requirement (`protocol_function_declaration`) has no body and is
1660
+ // always a member; an ordinary `function_declaration` is a method exactly when
1661
+ // it is nested in a type (or an extension of one).
1662
+ if (node.type === "function_declaration" || node.type === "protocol_function_declaration") {
1663
+ const name = funcName();
1664
+ if (!name)
1665
+ return null;
1666
+ const kind = node.type === "protocol_function_declaration" ||
1667
+ SWIFT_TYPE_KINDS.has(ctx.enclosingKind ?? "file")
1668
+ ? "method"
1669
+ : "function";
1670
+ return {
1671
+ name,
1672
+ kind,
1673
+ headerEnd: headEnd("function_body"),
1674
+ hashNode: node,
1675
+ ...swiftArity(node),
1676
+ };
1677
+ }
1678
+ if (node.type === "init_declaration") {
1679
+ // Initializers carry no name of their own — they are the type's own, so scope
1680
+ // the node under the enclosing type the same way Java's constructor_declaration
1681
+ // does. (A protocol's `init` requirement lands here too, owned by the protocol.)
1682
+ if (!ctx.enclosingClass)
1683
+ return null;
1684
+ return {
1685
+ name: ctx.enclosingClass,
1686
+ kind: "method",
1687
+ headerEnd: headEnd("function_body"),
1688
+ hashNode: node,
1689
+ ...swiftArity(node),
1690
+ };
1691
+ }
1692
+ if (node.type === "typealias_declaration") {
1693
+ const name = typeName();
1694
+ if (!name)
1695
+ return null;
1696
+ return { name, kind: "type", headerEnd: node.endIndex, hashNode: node };
1697
+ }
1698
+ if (node.type === "property_declaration") {
1699
+ // Top-level `let`/`var` only — a stored/computed property inside a type is a
1700
+ // field, not a definition node (no depth tier emits fields), so it must not
1701
+ // become one. `deinit` and `subscript` are likewise skipped: neither is ever
1702
+ // the target of a resolvable call edge, and neither carries a usable name.
1703
+ if (ctx.enclosingKind !== null)
1704
+ return null;
1705
+ const name = node.namedChildren
1706
+ .find((c) => c.type === "pattern")
1707
+ ?.namedChildren.find((c) => c.type === "simple_identifier")?.text;
1708
+ if (!name)
1709
+ return null;
1710
+ return { name, kind: "variable", headerEnd: node.endIndex, hashNode: node };
1711
+ }
1712
+ return null;
1713
+ }
1492
1714
  /** Java visibility: `public` (or `protected`) on the declaration's own modifier list.
1493
1715
  * A package-private or private member is not part of the API surface. Read off the
1494
1716
  * `modifiers` child's tokens, ignoring annotations, which live in the same node. */
@@ -1507,6 +1729,56 @@ function kotlinExported(node) {
1507
1729
  const vis = mods.namedChildren.find((c) => c.type === "visibility_modifier");
1508
1730
  return !vis || vis.text === "public";
1509
1731
  }
1732
+ /** Declared parameter count for a Swift callable, for overload disambiguation
1733
+ * (the same role Java's `arity`/`argCount` pair plays). `parameter` nodes are
1734
+ * direct children of the declaration; a default value's `=` sits as a SIBLING
1735
+ * token after its parameter, and a variadic `...` sits inside its parameter.
1736
+ * `arity` is the REQUIRED minimum (parameters minus defaults) and `variadic`
1737
+ * marks any default or variadic parameter, so `narrowByArity`'s at-least
1738
+ * semantics keeps every overload a call of that shape could reach. */
1739
+ function swiftArity(node) {
1740
+ const params = node.children.filter((c) => c.type === "parameter");
1741
+ const defaults = node.children.filter((c) => c.type === "=").length;
1742
+ const hasVariadic = params.some((p) => p.children.some((c) => c.type === "..."));
1743
+ const arity = Math.max(0, params.length - defaults);
1744
+ return hasVariadic || defaults > 0 ? { arity, variadic: true } : { arity };
1745
+ }
1746
+ /** Argument count at a Swift call site: the `value_argument`s plus one for a
1747
+ * trailing closure (`run(x) { … }` calls a two-parameter function). */
1748
+ function swiftArgCount(node) {
1749
+ const suffix = node.namedChildren.find((c) => c.type === "call_suffix");
1750
+ if (!suffix)
1751
+ return undefined;
1752
+ const args = suffix.namedChildren
1753
+ .find((c) => c.type === "value_arguments")
1754
+ ?.namedChildren.filter((c) => c.type === "value_argument").length ?? 0;
1755
+ const trailing = suffix.namedChildren.some((c) => c.type === "lambda_literal") ? 1 : 0;
1756
+ return args + trailing;
1757
+ }
1758
+ /** Swift visibility: the default (`internal`) is module-wide, and a repo is
1759
+ * typically one module — so `public` / `open` / `package` / `internal` all count
1760
+ * as API surface, and only an explicit `private` / `fileprivate` hides a
1761
+ * definition. A setter-only restriction (`private(set)`) leaves the getter
1762
+ * visible, so it does not hide the symbol either. */
1763
+ function swiftExported(node) {
1764
+ const mods = node.namedChildren.find((c) => c.type === "modifiers");
1765
+ const vis = mods?.namedChildren.find((c) => c.type === "visibility_modifier");
1766
+ return !vis || (vis.text !== "private" && vis.text !== "fileprivate");
1767
+ }
1768
+ /** The superclass a Swift class declaration names: its FIRST inheritance
1769
+ * specifier — Swift's grammar requires the superclass to precede any protocol
1770
+ * in the `:` list, so when a superclass exists it is always this entry. A
1771
+ * class conforming only to protocols yields that protocol's name instead, but
1772
+ * `super` is illegal in such a class, so no call site ever consults it. Null
1773
+ * for a bare `class Foo` (and for an extension, whose declaration carries no
1774
+ * heritage for the original type — `super` inside one stays unresolved). */
1775
+ function swiftSuperClassName(node) {
1776
+ const spec = node.namedChildren.find((c) => c.type === "inheritance_specifier");
1777
+ const ids = spec?.namedChildren
1778
+ .find((c) => c.type === "user_type")
1779
+ ?.namedChildren.filter((c) => c.type === "type_identifier");
1780
+ return ids?.length ? ids[ids.length - 1].text : null;
1781
+ }
1510
1782
  /** The receiver's base type name for a Go method, unwrapping a pointer receiver
1511
1783
  * (`func (u *User) …` → `User`). Null if it can't be read. */
1512
1784
  function goReceiverType(node) {
@@ -1593,6 +1865,27 @@ function heritageEdges(node, classId, ctx) {
1593
1865
  }
1594
1866
  return edges;
1595
1867
  }
1868
+ if (ctx.lang === "swift") {
1869
+ // `class A: B, C` — each `inheritance_specifier` (a direct child of the
1870
+ // declaration; protocols and extensions carry them too) wraps a `user_type`
1871
+ // whose LAST direct `type_identifier` is the bare supertype name: a
1872
+ // module-qualified `Foundation.NSObject` reduces to `NSObject`, and generic
1873
+ // arguments live in nested nodes so they never leak in. Swift cannot say
1874
+ // syntactically whether a specifier is the superclass or a protocol
1875
+ // conformance (that needs the target's kind), so every edge is `extends` —
1876
+ // the same collapse Kotlin's delegation specifiers make.
1877
+ for (const child of node.namedChildren) {
1878
+ if (child.type !== "inheritance_specifier")
1879
+ continue;
1880
+ const ids = child.namedChildren
1881
+ .find((c) => c.type === "user_type")
1882
+ ?.namedChildren.filter((c) => c.type === "type_identifier");
1883
+ const t = ids?.length ? ids[ids.length - 1] : undefined;
1884
+ if (t)
1885
+ edges.push({ source: classId, relation: "extends", name: t.text, file: ctx.rel });
1886
+ }
1887
+ return edges;
1888
+ }
1596
1889
  if (ctx.lang === "python") {
1597
1890
  const supers = node.childForFieldName("superclasses"); // argument_list
1598
1891
  for (const c of supers?.namedChildren ?? []) {
@@ -1758,6 +2051,47 @@ function calleeName(node, lang) {
1758
2051
  }
1759
2052
  return null;
1760
2053
  }
2054
+ if (lang === "swift") {
2055
+ // Same shape as Kotlin's: `call_expression` = callee expression + `call_suffix`.
2056
+ // A bare `foo()` names a plain call (this also covers `Animal()` initializer
2057
+ // calls, which have no distinguishing syntax); `obj.foo()` is a
2058
+ // `navigation_expression` whose trailing `navigation_suffix` holds the member
2059
+ // name and whose head is the receiver.
2060
+ const target = node.namedChildren[0];
2061
+ if (target?.type === "simple_identifier")
2062
+ return { name: target.text, viaMember: false };
2063
+ if (target?.type === "navigation_expression") {
2064
+ const suffix = target.namedChildren.find((c) => c.type === "navigation_suffix");
2065
+ const name = suffix?.namedChildren.find((c) => c.type === "simple_identifier");
2066
+ const receiver = target.namedChildren[0];
2067
+ if (!name)
2068
+ return null;
2069
+ if (receiver?.type === "simple_identifier")
2070
+ return { name: name.text, viaMember: true, receiver: receiver.text };
2071
+ if (receiver?.type === "self_expression" || receiver?.type === "super_expression")
2072
+ return {
2073
+ name: name.text,
2074
+ viaMember: true,
2075
+ receiver: receiver.type === "self_expression" ? "self" : "super",
2076
+ };
2077
+ if (receiver?.type === "navigation_expression") {
2078
+ // `self.repo.save()` — one hop off self is a field access and binds like
2079
+ // TS's `this.x`. Deeper chains and call-result receivers carry no
2080
+ // confident local clue, so those fall through with no receiver.
2081
+ const head = receiver.namedChildren[0];
2082
+ const field = receiver.namedChildren
2083
+ .find((c) => c.type === "navigation_suffix")
2084
+ ?.namedChildren.find((c) => c.type === "simple_identifier");
2085
+ if (head?.type === "self_expression" && field)
2086
+ return { name: name.text, viaMember: true, receiver: `self.${field.text}` };
2087
+ }
2088
+ // Still a member call even with an unknowable receiver (a chained call, a
2089
+ // literal, a subscript): recvType stays unset and resolve drops it rather
2090
+ // than guessing — same contract as Java's and TS's unknown receivers.
2091
+ return { name: name.text, viaMember: true };
2092
+ }
2093
+ return null;
2094
+ }
1761
2095
  if (lang === "php")
1762
2096
  return phpCallee(node);
1763
2097
  const fn = node.childForFieldName("function");
@@ -1987,6 +2321,8 @@ function isImport(node, lang) {
1987
2321
  return node.type === "import_declaration";
1988
2322
  if (lang === "kotlin")
1989
2323
  return node.type === "import_header";
2324
+ if (lang === "swift")
2325
+ return node.type === "import_declaration";
1990
2326
  // PHP: one edge per imported symbol — the clause leaf inside a (possibly
1991
2327
  // grouped) `use A\B, C\D;` / `use A\{B, C};` declaration.
1992
2328
  if (lang === "php")
@@ -2030,6 +2366,14 @@ function importSpecifier(node, lang) {
2030
2366
  // identifier text is already the module path (wildcards dropped, like Java).
2031
2367
  return node.namedChildren.find((c) => c.type === "identifier")?.text ?? null;
2032
2368
  }
2369
+ if (lang === "swift") {
2370
+ // `import UIKit` / `import struct Foundation.Date` — the dotted path is the
2371
+ // `identifier` child (an import-kind keyword like `struct` is a separate
2372
+ // token). Swift imports name MODULES, not files, so the specifier resolves
2373
+ // to a repo file only when a same-named module target exists; external
2374
+ // frameworks stay as unresolved (but truthful) import intents.
2375
+ return node.namedChildren.find((c) => c.type === "identifier")?.text ?? null;
2376
+ }
2033
2377
  const str = node.namedChildren.find((c) => c.type === "string");
2034
2378
  if (!str)
2035
2379
  return null;