gitnexus 1.5.3 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/README.md +10 -0
  2. package/dist/_shared/graph/types.d.ts +1 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +1 -0
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/language-detection.d.ts.map +1 -1
  7. package/dist/_shared/language-detection.js +2 -0
  8. package/dist/_shared/language-detection.js.map +1 -1
  9. package/dist/_shared/languages.d.ts +1 -0
  10. package/dist/_shared/languages.d.ts.map +1 -1
  11. package/dist/_shared/languages.js +1 -0
  12. package/dist/_shared/languages.js.map +1 -1
  13. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  14. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.js +3 -1
  16. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  17. package/dist/_shared/mro-strategy.d.ts +19 -0
  18. package/dist/_shared/mro-strategy.d.ts.map +1 -0
  19. package/dist/_shared/mro-strategy.js +2 -0
  20. package/dist/_shared/mro-strategy.js.map +1 -0
  21. package/dist/cli/ai-context.d.ts +1 -0
  22. package/dist/cli/ai-context.js +28 -4
  23. package/dist/cli/analyze.d.ts +2 -0
  24. package/dist/cli/analyze.js +30 -4
  25. package/dist/cli/group.d.ts +2 -0
  26. package/dist/cli/group.js +233 -0
  27. package/dist/cli/index.js +3 -0
  28. package/dist/cli/serve.js +4 -1
  29. package/dist/cli/setup.js +34 -3
  30. package/dist/config/ignore-service.js +8 -3
  31. package/dist/core/augmentation/engine.js +1 -1
  32. package/dist/core/git-staleness.d.ts +13 -0
  33. package/dist/core/git-staleness.js +29 -0
  34. package/dist/core/group/bridge-db.d.ts +82 -0
  35. package/dist/core/group/bridge-db.js +460 -0
  36. package/dist/core/group/bridge-schema.d.ts +27 -0
  37. package/dist/core/group/bridge-schema.js +55 -0
  38. package/dist/core/group/config-parser.d.ts +3 -0
  39. package/dist/core/group/config-parser.js +83 -0
  40. package/dist/core/group/contract-extractor.d.ts +7 -0
  41. package/dist/core/group/contract-extractor.js +1 -0
  42. package/dist/core/group/extractors/fs-utils.d.ts +10 -0
  43. package/dist/core/group/extractors/fs-utils.js +24 -0
  44. package/dist/core/group/extractors/grpc-extractor.d.ts +25 -0
  45. package/dist/core/group/extractors/grpc-extractor.js +386 -0
  46. package/dist/core/group/extractors/grpc-patterns/go.d.ts +2 -0
  47. package/dist/core/group/extractors/grpc-patterns/go.js +97 -0
  48. package/dist/core/group/extractors/grpc-patterns/index.d.ts +19 -0
  49. package/dist/core/group/extractors/grpc-patterns/index.js +46 -0
  50. package/dist/core/group/extractors/grpc-patterns/java.d.ts +2 -0
  51. package/dist/core/group/extractors/grpc-patterns/java.js +173 -0
  52. package/dist/core/group/extractors/grpc-patterns/node.d.ts +4 -0
  53. package/dist/core/group/extractors/grpc-patterns/node.js +290 -0
  54. package/dist/core/group/extractors/grpc-patterns/proto.d.ts +9 -0
  55. package/dist/core/group/extractors/grpc-patterns/proto.js +134 -0
  56. package/dist/core/group/extractors/grpc-patterns/python.d.ts +2 -0
  57. package/dist/core/group/extractors/grpc-patterns/python.js +67 -0
  58. package/dist/core/group/extractors/grpc-patterns/types.d.ts +50 -0
  59. package/dist/core/group/extractors/grpc-patterns/types.js +1 -0
  60. package/dist/core/group/extractors/http-patterns/go.d.ts +2 -0
  61. package/dist/core/group/extractors/http-patterns/go.js +215 -0
  62. package/dist/core/group/extractors/http-patterns/index.d.ts +17 -0
  63. package/dist/core/group/extractors/http-patterns/index.js +44 -0
  64. package/dist/core/group/extractors/http-patterns/java.d.ts +2 -0
  65. package/dist/core/group/extractors/http-patterns/java.js +253 -0
  66. package/dist/core/group/extractors/http-patterns/node.d.ts +4 -0
  67. package/dist/core/group/extractors/http-patterns/node.js +354 -0
  68. package/dist/core/group/extractors/http-patterns/php.d.ts +2 -0
  69. package/dist/core/group/extractors/http-patterns/php.js +70 -0
  70. package/dist/core/group/extractors/http-patterns/python.d.ts +2 -0
  71. package/dist/core/group/extractors/http-patterns/python.js +133 -0
  72. package/dist/core/group/extractors/http-patterns/types.d.ts +61 -0
  73. package/dist/core/group/extractors/http-patterns/types.js +1 -0
  74. package/dist/core/group/extractors/http-route-extractor.d.ts +21 -0
  75. package/dist/core/group/extractors/http-route-extractor.js +391 -0
  76. package/dist/core/group/extractors/manifest-extractor.d.ts +54 -0
  77. package/dist/core/group/extractors/manifest-extractor.js +235 -0
  78. package/dist/core/group/extractors/topic-extractor.d.ts +8 -0
  79. package/dist/core/group/extractors/topic-extractor.js +97 -0
  80. package/dist/core/group/extractors/topic-patterns/go.d.ts +2 -0
  81. package/dist/core/group/extractors/topic-patterns/go.js +120 -0
  82. package/dist/core/group/extractors/topic-patterns/index.d.ts +14 -0
  83. package/dist/core/group/extractors/topic-patterns/index.js +38 -0
  84. package/dist/core/group/extractors/topic-patterns/java.d.ts +2 -0
  85. package/dist/core/group/extractors/topic-patterns/java.js +80 -0
  86. package/dist/core/group/extractors/topic-patterns/node.d.ts +4 -0
  87. package/dist/core/group/extractors/topic-patterns/node.js +155 -0
  88. package/dist/core/group/extractors/topic-patterns/python.d.ts +2 -0
  89. package/dist/core/group/extractors/topic-patterns/python.js +116 -0
  90. package/dist/core/group/extractors/topic-patterns/types.d.ts +25 -0
  91. package/dist/core/group/extractors/topic-patterns/types.js +10 -0
  92. package/dist/core/group/extractors/tree-sitter-scanner.d.ts +113 -0
  93. package/dist/core/group/extractors/tree-sitter-scanner.js +94 -0
  94. package/dist/core/group/matching.d.ts +13 -0
  95. package/dist/core/group/matching.js +198 -0
  96. package/dist/core/group/normalization.d.ts +3 -0
  97. package/dist/core/group/normalization.js +115 -0
  98. package/dist/core/group/service-boundary-detector.d.ts +8 -0
  99. package/dist/core/group/service-boundary-detector.js +155 -0
  100. package/dist/core/group/service.d.ts +46 -0
  101. package/dist/core/group/service.js +160 -0
  102. package/dist/core/group/storage.d.ts +9 -0
  103. package/dist/core/group/storage.js +91 -0
  104. package/dist/core/group/sync.d.ts +21 -0
  105. package/dist/core/group/sync.js +148 -0
  106. package/dist/core/group/types.d.ts +130 -0
  107. package/dist/core/group/types.js +1 -0
  108. package/dist/core/ingestion/binding-accumulator.d.ts +212 -0
  109. package/dist/core/ingestion/binding-accumulator.js +336 -0
  110. package/dist/core/ingestion/call-processor.d.ts +155 -24
  111. package/dist/core/ingestion/call-processor.js +1129 -247
  112. package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
  113. package/dist/core/ingestion/class-extractors/generic.js +135 -0
  114. package/dist/core/ingestion/class-types.d.ts +34 -0
  115. package/dist/core/ingestion/class-types.js +1 -0
  116. package/dist/core/ingestion/cobol-processor.d.ts +1 -1
  117. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
  118. package/dist/core/ingestion/entry-point-scoring.js +1 -0
  119. package/dist/core/ingestion/field-types.d.ts +2 -2
  120. package/dist/core/ingestion/filesystem-walker.js +8 -0
  121. package/dist/core/ingestion/framework-detection.d.ts +1 -0
  122. package/dist/core/ingestion/framework-detection.js +1 -0
  123. package/dist/core/ingestion/heritage-processor.d.ts +8 -15
  124. package/dist/core/ingestion/heritage-processor.js +15 -28
  125. package/dist/core/ingestion/import-processor.d.ts +1 -11
  126. package/dist/core/ingestion/import-processor.js +1 -13
  127. package/dist/core/ingestion/import-resolvers/utils.js +1 -0
  128. package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
  129. package/dist/core/ingestion/import-resolvers/vue.js +9 -0
  130. package/dist/core/ingestion/language-config.js +1 -1
  131. package/dist/core/ingestion/language-provider.d.ts +14 -3
  132. package/dist/core/ingestion/languages/c-cpp.js +168 -1
  133. package/dist/core/ingestion/languages/csharp.js +20 -0
  134. package/dist/core/ingestion/languages/dart.js +26 -4
  135. package/dist/core/ingestion/languages/go.js +22 -0
  136. package/dist/core/ingestion/languages/index.d.ts +1 -0
  137. package/dist/core/ingestion/languages/index.js +2 -0
  138. package/dist/core/ingestion/languages/java.js +17 -0
  139. package/dist/core/ingestion/languages/kotlin.js +24 -1
  140. package/dist/core/ingestion/languages/php.js +23 -11
  141. package/dist/core/ingestion/languages/python.js +9 -0
  142. package/dist/core/ingestion/languages/ruby.js +43 -0
  143. package/dist/core/ingestion/languages/rust.js +38 -0
  144. package/dist/core/ingestion/languages/swift.js +31 -0
  145. package/dist/core/ingestion/languages/typescript.d.ts +1 -0
  146. package/dist/core/ingestion/languages/typescript.js +52 -3
  147. package/dist/core/ingestion/languages/vue.d.ts +13 -0
  148. package/dist/core/ingestion/languages/vue.js +81 -0
  149. package/dist/core/ingestion/markdown-processor.d.ts +1 -1
  150. package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
  151. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  152. package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
  153. package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
  154. package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
  155. package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
  156. package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
  157. package/dist/core/ingestion/method-extractors/configs/jvm.js +14 -4
  158. package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
  159. package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
  160. package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
  161. package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
  162. package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
  163. package/dist/core/ingestion/method-extractors/configs/ruby.js +286 -0
  164. package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
  165. package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
  166. package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
  167. package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
  168. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +85 -8
  169. package/dist/core/ingestion/method-extractors/generic.d.ts +6 -0
  170. package/dist/core/ingestion/method-extractors/generic.js +84 -17
  171. package/dist/core/ingestion/method-types.d.ts +29 -0
  172. package/dist/core/ingestion/model/field-registry.d.ts +18 -0
  173. package/dist/core/ingestion/model/field-registry.js +22 -0
  174. package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
  175. package/dist/core/ingestion/model/heritage-map.js +159 -0
  176. package/dist/core/ingestion/model/index.d.ts +20 -0
  177. package/dist/core/ingestion/model/index.js +41 -0
  178. package/dist/core/ingestion/model/method-registry.d.ts +62 -0
  179. package/dist/core/ingestion/model/method-registry.js +130 -0
  180. package/dist/core/ingestion/model/registration-table.d.ts +139 -0
  181. package/dist/core/ingestion/model/registration-table.js +224 -0
  182. package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
  183. package/dist/core/ingestion/model/resolution-context.js +337 -0
  184. package/dist/core/ingestion/model/resolve.d.ts +56 -0
  185. package/dist/core/ingestion/model/resolve.js +297 -0
  186. package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
  187. package/dist/core/ingestion/model/semantic-model.js +120 -0
  188. package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
  189. package/dist/core/ingestion/model/symbol-table.js +206 -0
  190. package/dist/core/ingestion/model/type-registry.d.ts +39 -0
  191. package/dist/core/ingestion/model/type-registry.js +62 -0
  192. package/dist/core/ingestion/mro-processor.d.ts +5 -4
  193. package/dist/core/ingestion/mro-processor.js +311 -107
  194. package/dist/core/ingestion/parsing-processor.d.ts +5 -4
  195. package/dist/core/ingestion/parsing-processor.js +224 -87
  196. package/dist/core/ingestion/pipeline-phases/cobol.d.ts +16 -0
  197. package/dist/core/ingestion/pipeline-phases/cobol.js +45 -0
  198. package/dist/core/ingestion/pipeline-phases/communities.d.ts +16 -0
  199. package/dist/core/ingestion/pipeline-phases/communities.js +62 -0
  200. package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +17 -0
  201. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +156 -0
  202. package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +37 -0
  203. package/dist/core/ingestion/pipeline-phases/cross-file.js +63 -0
  204. package/dist/core/ingestion/pipeline-phases/index.d.ts +21 -0
  205. package/dist/core/ingestion/pipeline-phases/index.js +22 -0
  206. package/dist/core/ingestion/pipeline-phases/markdown.d.ts +17 -0
  207. package/dist/core/ingestion/pipeline-phases/markdown.js +33 -0
  208. package/dist/core/ingestion/pipeline-phases/mro.d.ts +18 -0
  209. package/dist/core/ingestion/pipeline-phases/mro.js +36 -0
  210. package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +22 -0
  211. package/dist/core/ingestion/pipeline-phases/orm-extraction.js +92 -0
  212. package/dist/core/ingestion/pipeline-phases/orm.d.ts +15 -0
  213. package/dist/core/ingestion/pipeline-phases/orm.js +74 -0
  214. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +47 -0
  215. package/dist/core/ingestion/pipeline-phases/parse-impl.js +437 -0
  216. package/dist/core/ingestion/pipeline-phases/parse.d.ts +49 -0
  217. package/dist/core/ingestion/pipeline-phases/parse.js +33 -0
  218. package/dist/core/ingestion/pipeline-phases/processes.d.ts +16 -0
  219. package/dist/core/ingestion/pipeline-phases/processes.js +143 -0
  220. package/dist/core/ingestion/pipeline-phases/routes.d.ts +21 -0
  221. package/dist/core/ingestion/pipeline-phases/routes.js +243 -0
  222. package/dist/core/ingestion/pipeline-phases/runner.d.ts +22 -0
  223. package/dist/core/ingestion/pipeline-phases/runner.js +203 -0
  224. package/dist/core/ingestion/pipeline-phases/scan.d.ts +21 -0
  225. package/dist/core/ingestion/pipeline-phases/scan.js +46 -0
  226. package/dist/core/ingestion/pipeline-phases/structure.d.ts +27 -0
  227. package/dist/core/ingestion/pipeline-phases/structure.js +35 -0
  228. package/dist/core/ingestion/pipeline-phases/tools.d.ts +20 -0
  229. package/dist/core/ingestion/pipeline-phases/tools.js +79 -0
  230. package/dist/core/ingestion/pipeline-phases/types.d.ts +79 -0
  231. package/dist/core/ingestion/pipeline-phases/types.js +37 -0
  232. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +35 -0
  233. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +174 -0
  234. package/dist/core/ingestion/pipeline.d.ts +18 -10
  235. package/dist/core/ingestion/pipeline.js +66 -1410
  236. package/dist/core/ingestion/process-processor.js +1 -1
  237. package/dist/core/ingestion/tree-sitter-queries.d.ts +5 -5
  238. package/dist/core/ingestion/tree-sitter-queries.js +90 -0
  239. package/dist/core/ingestion/type-env.d.ts +15 -2
  240. package/dist/core/ingestion/type-env.js +163 -102
  241. package/dist/core/ingestion/type-extractors/csharp.js +17 -0
  242. package/dist/core/ingestion/type-extractors/jvm.js +11 -0
  243. package/dist/core/ingestion/type-extractors/php.js +0 -55
  244. package/dist/core/ingestion/type-extractors/ruby.js +0 -32
  245. package/dist/core/ingestion/type-extractors/swift.js +13 -0
  246. package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
  247. package/dist/core/ingestion/type-extractors/typescript.js +66 -69
  248. package/dist/core/ingestion/utils/ast-helpers.d.ts +32 -44
  249. package/dist/core/ingestion/utils/ast-helpers.js +157 -573
  250. package/dist/core/ingestion/utils/env.d.ts +10 -0
  251. package/dist/core/ingestion/utils/env.js +10 -0
  252. package/dist/core/ingestion/utils/graph-sort.d.ts +58 -0
  253. package/dist/core/ingestion/utils/graph-sort.js +100 -0
  254. package/dist/core/ingestion/utils/method-props.d.ts +32 -0
  255. package/dist/core/ingestion/utils/method-props.js +147 -0
  256. package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
  257. package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
  258. package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
  259. package/dist/core/ingestion/workers/parse-worker.js +469 -200
  260. package/dist/core/lbug/lbug-adapter.d.ts +6 -0
  261. package/dist/core/lbug/lbug-adapter.js +134 -27
  262. package/dist/core/lbug/pool-adapter.d.ts +76 -0
  263. package/dist/core/lbug/pool-adapter.js +522 -0
  264. package/dist/core/run-analyze.d.ts +2 -0
  265. package/dist/core/run-analyze.js +1 -1
  266. package/dist/core/search/bm25-index.js +1 -1
  267. package/dist/core/tree-sitter/parser-loader.js +1 -0
  268. package/dist/core/wiki/graph-queries.js +1 -1
  269. package/dist/mcp/core/embedder.js +6 -5
  270. package/dist/mcp/core/lbug-adapter.d.ts +3 -63
  271. package/dist/mcp/core/lbug-adapter.js +3 -484
  272. package/dist/mcp/local/local-backend.d.ts +31 -2
  273. package/dist/mcp/local/local-backend.js +255 -46
  274. package/dist/mcp/resources.js +5 -4
  275. package/dist/mcp/staleness.d.ts +3 -13
  276. package/dist/mcp/staleness.js +2 -31
  277. package/dist/mcp/tools.js +80 -4
  278. package/dist/server/analyze-job.d.ts +2 -0
  279. package/dist/server/analyze-job.js +4 -0
  280. package/dist/server/api.d.ts +20 -1
  281. package/dist/server/api.js +306 -71
  282. package/dist/server/git-clone.d.ts +2 -1
  283. package/dist/server/git-clone.js +98 -5
  284. package/dist/storage/git.d.ts +13 -0
  285. package/dist/storage/git.js +25 -0
  286. package/dist/storage/repo-manager.js +1 -1
  287. package/package.json +9 -3
  288. package/scripts/patch-tree-sitter-swift.cjs +78 -0
  289. package/vendor/tree-sitter-proto/binding.gyp +30 -0
  290. package/vendor/tree-sitter-proto/bindings/node/binding.cc +20 -0
  291. package/vendor/tree-sitter-proto/bindings/node/index.d.ts +28 -0
  292. package/vendor/tree-sitter-proto/bindings/node/index.js +7 -0
  293. package/vendor/tree-sitter-proto/package.json +18 -0
  294. package/vendor/tree-sitter-proto/src/node-types.json +1145 -0
  295. package/vendor/tree-sitter-proto/src/parser.c +10149 -0
  296. package/vendor/tree-sitter-proto/src/tree_sitter/alloc.h +54 -0
  297. package/vendor/tree-sitter-proto/src/tree_sitter/array.h +291 -0
  298. package/vendor/tree-sitter-proto/src/tree_sitter/parser.h +266 -0
  299. package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
  300. package/dist/core/ingestion/named-binding-processor.js +0 -42
  301. package/dist/core/ingestion/resolution-context.d.ts +0 -58
  302. package/dist/core/ingestion/resolution-context.js +0 -135
  303. package/dist/core/ingestion/symbol-table.d.ts +0 -79
  304. package/dist/core/ingestion/symbol-table.js +0 -115
@@ -0,0 +1,277 @@
1
+ // gitnexus/src/core/ingestion/method-extractors/configs/swift.ts
2
+ // Verified against tree-sitter-swift 0.6.0
3
+ import { SupportedLanguages } from '../../../../_shared/index.js';
4
+ import { findVisibility, hasKeyword, hasModifier } from '../../field-extractors/configs/helpers.js';
5
+ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
6
+ // ---------------------------------------------------------------------------
7
+ // Swift helpers
8
+ // ---------------------------------------------------------------------------
9
+ const SWIFT_VIS = new Set([
10
+ 'public',
11
+ 'private',
12
+ 'fileprivate',
13
+ 'internal',
14
+ 'open',
15
+ ]);
16
+ /**
17
+ * Extract the method name from a function_declaration or protocol_function_declaration.
18
+ *
19
+ * In tree-sitter-swift, the name is stored in a `simple_identifier` child
20
+ * (not a 'name' field) on both function_declaration and protocol_function_declaration.
21
+ */
22
+ function extractSwiftName(node) {
23
+ // Try field-based name first
24
+ const nameField = node.childForFieldName('name');
25
+ if (nameField)
26
+ return nameField.text;
27
+ // Walk named children for simple_identifier (the function name)
28
+ for (let i = 0; i < node.namedChildCount; i++) {
29
+ const child = node.namedChild(i);
30
+ if (child?.type === 'simple_identifier')
31
+ return child.text;
32
+ }
33
+ return undefined;
34
+ }
35
+ /**
36
+ * Extract the return type from a Swift function declaration.
37
+ *
38
+ * In tree-sitter-swift, the return type appears in a `type_annotation` child
39
+ * that follows the parameter list (after `->` in source). It may also appear
40
+ * as a direct type child (user_type, optional_type, tuple_type, array_type).
41
+ */
42
+ function extractSwiftReturnType(node) {
43
+ // Look for the return type — typically the last type_annotation or a type node
44
+ // that appears after the parameter list.
45
+ // tree-sitter-swift places the return type inside a type child after '->'
46
+ let seenParams = false;
47
+ for (let i = 0; i < node.namedChildCount; i++) {
48
+ const child = node.namedChild(i);
49
+ if (!child)
50
+ continue;
51
+ if (child.type === 'parameter') {
52
+ seenParams = true;
53
+ continue;
54
+ }
55
+ // The parameter list may be unnamed children; track when we pass ')'
56
+ if (seenParams || child.type === 'type_annotation') {
57
+ if (child.type === 'type_annotation') {
58
+ const inner = child.firstNamedChild;
59
+ if (inner)
60
+ return inner.text?.trim();
61
+ }
62
+ if (child.type === 'user_type' ||
63
+ child.type === 'optional_type' ||
64
+ child.type === 'tuple_type' ||
65
+ child.type === 'array_type' ||
66
+ child.type === 'dictionary_type' ||
67
+ child.type === 'function_type') {
68
+ return child.text?.trim();
69
+ }
70
+ }
71
+ }
72
+ // Fallback: scan all children (named + unnamed) for '->' then grab the next named child
73
+ let seenArrow = false;
74
+ for (let i = 0; i < node.childCount; i++) {
75
+ const child = node.child(i);
76
+ if (!child)
77
+ continue;
78
+ if (!child.isNamed && child.text.trim() === '->') {
79
+ seenArrow = true;
80
+ continue;
81
+ }
82
+ if (seenArrow && child.isNamed) {
83
+ return child.text?.trim();
84
+ }
85
+ }
86
+ return undefined;
87
+ }
88
+ /**
89
+ * Extract parameters from a Swift function declaration.
90
+ *
91
+ * In tree-sitter-swift, parameters are `parameter` named children directly on
92
+ * the function_declaration node. Each parameter has:
93
+ * - An external name (label) and/or internal name as simple_identifier children
94
+ * - A type_annotation child containing the type
95
+ * - An optional default value after '='
96
+ * - A possible `...` for variadic parameters
97
+ */
98
+ function extractSwiftParameters(node) {
99
+ const params = [];
100
+ // In tree-sitter-swift 0.6.0, parameters are direct children of function_declaration.
101
+ // Default value tokens ('=', literal) are siblings of the parameter node at the
102
+ // function_declaration level, not children of the parameter node.
103
+ for (let i = 0; i < node.childCount; i++) {
104
+ const child = node.child(i);
105
+ if (!child?.isNamed || child.type !== 'parameter')
106
+ continue;
107
+ // Extract parameter name — the last simple_identifier is the internal name
108
+ let paramName;
109
+ for (let j = 0; j < child.namedChildCount; j++) {
110
+ const part = child.namedChild(j);
111
+ if (part?.type === 'simple_identifier') {
112
+ paramName = part.text;
113
+ }
114
+ }
115
+ if (!paramName)
116
+ continue;
117
+ // Extract type — tree-sitter-swift uses user_type (not type_annotation)
118
+ let typeName = null;
119
+ let rawTypeName = null;
120
+ for (let j = 0; j < child.namedChildCount; j++) {
121
+ const part = child.namedChild(j);
122
+ if (part?.type === 'user_type' || part?.type === 'type_annotation') {
123
+ rawTypeName = part.text?.trim() ?? null;
124
+ const inner = part.firstNamedChild;
125
+ if (inner) {
126
+ typeName = extractSimpleTypeName(inner) ?? inner.text?.trim() ?? null;
127
+ }
128
+ else {
129
+ typeName = rawTypeName;
130
+ }
131
+ break;
132
+ }
133
+ // Handle built-in types (array_type, dictionary_type, optional_type, tuple_type)
134
+ if (part?.type.endsWith('_type') && part.type !== 'simple_identifier') {
135
+ rawTypeName = part.text?.trim() ?? null;
136
+ typeName = extractSimpleTypeName(part) ?? rawTypeName;
137
+ break;
138
+ }
139
+ }
140
+ // Check for default value: '=' token appears as a sibling after the parameter node
141
+ let isOptional = false;
142
+ const nextSibling = node.child(i + 1);
143
+ if (nextSibling && !nextSibling.isNamed && nextSibling.text.trim() === '=') {
144
+ isOptional = true;
145
+ }
146
+ // Check for variadic: '...' token among parameter children
147
+ let isVariadic = false;
148
+ for (let j = 0; j < child.childCount; j++) {
149
+ const c = child.child(j);
150
+ if (c && c.text.trim() === '...') {
151
+ isVariadic = true;
152
+ break;
153
+ }
154
+ }
155
+ params.push({
156
+ name: paramName,
157
+ type: typeName,
158
+ rawType: rawTypeName,
159
+ isOptional,
160
+ isVariadic,
161
+ });
162
+ }
163
+ return params;
164
+ }
165
+ /**
166
+ * Check if a method is inside a protocol.
167
+ *
168
+ * A protocol_function_declaration is always abstract. For function_declaration
169
+ * inside a protocol_body (if it appears there), it's also abstract when it has
170
+ * no body.
171
+ */
172
+ function isSwiftAbstract(node, ownerNode) {
173
+ // protocol_function_declaration nodes are inherently abstract
174
+ if (node.type === 'protocol_function_declaration')
175
+ return true;
176
+ // function_declaration inside a protocol is abstract if it has no body
177
+ if (ownerNode.type === 'protocol_declaration') {
178
+ const body = node.childForFieldName('body');
179
+ if (!body) {
180
+ // Also check for function_body named child
181
+ for (let i = 0; i < node.namedChildCount; i++) {
182
+ const child = node.namedChild(i);
183
+ if (child?.type === 'function_body')
184
+ return false;
185
+ }
186
+ return true;
187
+ }
188
+ return false;
189
+ }
190
+ return false;
191
+ }
192
+ /**
193
+ * Collect attribute nodes from a Swift function declaration.
194
+ *
195
+ * In tree-sitter-swift, attributes appear as `attribute` named children
196
+ * directly on the function_declaration node, or inside a `modifiers` wrapper.
197
+ * Each attribute node text starts with '@'.
198
+ */
199
+ function extractSwiftAnnotations(node) {
200
+ const annotations = [];
201
+ for (let i = 0; i < node.namedChildCount; i++) {
202
+ const child = node.namedChild(i);
203
+ if (!child)
204
+ continue;
205
+ if (child.type === 'attribute') {
206
+ const text = child.text?.trim();
207
+ if (text) {
208
+ // Normalize: strip arguments, keep just the name
209
+ // e.g. "@objc(myMethod)" -> "@objc", "@available(iOS 13, *)" -> "@available"
210
+ const match = text.match(/^@(\w+)/);
211
+ if (match) {
212
+ annotations.push('@' + match[1]);
213
+ }
214
+ else {
215
+ annotations.push(text);
216
+ }
217
+ }
218
+ }
219
+ // Also check inside modifiers wrapper
220
+ if (child.type === 'modifiers') {
221
+ for (let j = 0; j < child.namedChildCount; j++) {
222
+ const mod = child.namedChild(j);
223
+ if (mod?.type === 'attribute') {
224
+ const text = mod.text?.trim();
225
+ if (text) {
226
+ const match = text.match(/^@(\w+)/);
227
+ if (match) {
228
+ annotations.push('@' + match[1]);
229
+ }
230
+ else {
231
+ annotations.push(text);
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+ }
238
+ return annotations;
239
+ }
240
+ // ---------------------------------------------------------------------------
241
+ // Swift config
242
+ // ---------------------------------------------------------------------------
243
+ export const swiftMethodConfig = {
244
+ language: SupportedLanguages.Swift,
245
+ // tree-sitter-swift 0.6.0 may use class_declaration for classes, structs, enums, extensions,
246
+ // and actors — but this cannot be verified until the grammar installs on Node 22+.
247
+ // TODO: Verify struct_declaration, enum_declaration, extension_declaration, actor_declaration
248
+ // node types once tree-sitter-swift loads on Node 22, and add them here if they are distinct.
249
+ // protocol_declaration is a separate, confirmed node type.
250
+ typeDeclarationNodes: ['class_declaration', 'protocol_declaration'],
251
+ // function_declaration for class/struct methods, protocol_function_declaration for protocol methods
252
+ methodNodeTypes: ['function_declaration', 'protocol_function_declaration'],
253
+ bodyNodeTypes: ['class_body', 'protocol_body'],
254
+ extractName: extractSwiftName,
255
+ extractReturnType: extractSwiftReturnType,
256
+ extractParameters: extractSwiftParameters,
257
+ extractVisibility(node) {
258
+ return findVisibility(node, SWIFT_VIS, 'internal', 'modifiers');
259
+ },
260
+ isStatic(node) {
261
+ return (hasKeyword(node, 'static') ||
262
+ hasKeyword(node, 'class') ||
263
+ hasModifier(node, 'modifiers', 'static') ||
264
+ hasModifier(node, 'modifiers', 'class'));
265
+ },
266
+ isAbstract: isSwiftAbstract,
267
+ isFinal(node) {
268
+ return hasKeyword(node, 'final') || hasModifier(node, 'modifiers', 'final');
269
+ },
270
+ isAsync(node) {
271
+ return hasKeyword(node, 'async') || hasModifier(node, 'modifiers', 'async');
272
+ },
273
+ isOverride(node) {
274
+ return hasKeyword(node, 'override') || hasModifier(node, 'modifiers', 'override');
275
+ },
276
+ extractAnnotations: extractSwiftAnnotations,
277
+ };
@@ -46,6 +46,7 @@ function extractTsJsParameters(node) {
46
46
  type: typeNode
47
47
  ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
48
48
  : null,
49
+ rawType: typeNode?.text?.trim() ?? null,
49
50
  isOptional: hasDefault,
50
51
  isVariadic: isRest,
51
52
  });
@@ -62,6 +63,7 @@ function extractTsJsParameters(node) {
62
63
  type: typeNode
63
64
  ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
64
65
  : null,
66
+ rawType: typeNode?.text?.trim() ?? null,
65
67
  isOptional: true,
66
68
  isVariadic: false,
67
69
  });
@@ -78,6 +80,7 @@ function extractTsJsParameters(node) {
78
80
  type: typeNode
79
81
  ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
80
82
  : null,
83
+ rawType: typeNode?.text?.trim() ?? null,
81
84
  isOptional: false,
82
85
  isVariadic: true,
83
86
  });
@@ -85,14 +88,26 @@ function extractTsJsParameters(node) {
85
88
  }
86
89
  case 'identifier': {
87
90
  // JS: bare parameter name, no type info
88
- params.push({ name: param.text, type: null, isOptional: false, isVariadic: false });
91
+ params.push({
92
+ name: param.text,
93
+ type: null,
94
+ rawType: null,
95
+ isOptional: false,
96
+ isVariadic: false,
97
+ });
89
98
  break;
90
99
  }
91
100
  case 'assignment_pattern': {
92
101
  // JS: param = defaultValue — the left side is the name, isOptional = true
93
102
  const left = param.childForFieldName('left');
94
103
  if (left) {
95
- params.push({ name: left.text, type: null, isOptional: true, isVariadic: false });
104
+ params.push({
105
+ name: left.text,
106
+ type: null,
107
+ rawType: null,
108
+ isOptional: true,
109
+ isVariadic: false,
110
+ });
96
111
  }
97
112
  break;
98
113
  }
@@ -100,22 +115,76 @@ function extractTsJsParameters(node) {
100
115
  // JS: ...args
101
116
  const inner = param.firstNamedChild;
102
117
  if (inner) {
103
- params.push({ name: inner.text, type: null, isOptional: false, isVariadic: true });
118
+ params.push({
119
+ name: inner.text,
120
+ type: null,
121
+ rawType: null,
122
+ isOptional: false,
123
+ isVariadic: true,
124
+ });
104
125
  }
105
126
  break;
106
127
  }
107
128
  case 'object_pattern':
108
129
  case 'array_pattern': {
109
130
  // Destructured parameter — use full text as name
110
- params.push({ name: param.text, type: null, isOptional: false, isVariadic: false });
131
+ params.push({
132
+ name: param.text,
133
+ type: null,
134
+ rawType: null,
135
+ isOptional: false,
136
+ isVariadic: false,
137
+ });
111
138
  break;
112
139
  }
113
140
  }
114
141
  }
115
142
  return params;
116
143
  }
144
+ /** Regex to extract @returns or @return from JSDoc comments: `@returns {Type}` */
145
+ const JSDOC_RETURN_RE = /@returns?\s*\{([^}]+)\}/;
146
+ /**
147
+ * Minimal sanitization for JSDoc return types — preserves generic wrappers
148
+ * (e.g. `Promise<User>`) so that extractReturnTypeName in call-processor
149
+ * can apply WRAPPER_GENERICS unwrapping. Only strips JSDoc-specific syntax markers.
150
+ */
151
+ function sanitizeJsDocReturnType(raw) {
152
+ let type = raw.trim();
153
+ // Strip JSDoc nullable/non-nullable prefixes: ?User → User, !User → User
154
+ if (type.startsWith('?') || type.startsWith('!'))
155
+ type = type.slice(1);
156
+ // Strip module: prefix — module:models.User → models.User
157
+ if (type.startsWith('module:'))
158
+ type = type.slice(7);
159
+ // Reject unions (ambiguous)
160
+ if (type.includes('|'))
161
+ return undefined;
162
+ if (!type)
163
+ return undefined;
164
+ return type;
165
+ }
166
+ /**
167
+ * Walk backwards through preceding siblings looking for a JSDoc comment containing
168
+ * `@returns {Type}` or `@return {Type}`. Stops at the first non-comment named node
169
+ * (excluding decorators, which precede methods in TS/JS).
170
+ */
171
+ function extractJsDocReturnType(node) {
172
+ let sibling = node.previousSibling;
173
+ while (sibling) {
174
+ if (sibling.type === 'comment') {
175
+ const match = JSDOC_RETURN_RE.exec(sibling.text);
176
+ if (match)
177
+ return sanitizeJsDocReturnType(match[1]);
178
+ }
179
+ else if (sibling.isNamed && sibling.type !== 'decorator')
180
+ break;
181
+ sibling = sibling.previousSibling;
182
+ }
183
+ return undefined;
184
+ }
117
185
  /**
118
186
  * Extract return type from return_type field, unwrapping type_annotation.
187
+ * Falls back to JSDoc `@returns {Type}` when the AST has no return type annotation.
119
188
  *
120
189
  * tree-sitter-typescript uses `return_type` as the field name (not `type` like JVM).
121
190
  * The return_type field points to a type_annotation node that must be unwrapped.
@@ -126,11 +195,12 @@ function extractTsJsReturnType(node) {
126
195
  if (returnType.type === 'type_annotation') {
127
196
  const inner = returnType.firstNamedChild;
128
197
  if (inner)
129
- return extractSimpleTypeName(inner) ?? inner.text?.trim();
198
+ return inner.text?.trim();
130
199
  }
131
- return extractSimpleTypeName(returnType) ?? returnType.text?.trim();
200
+ return returnType.text?.trim();
132
201
  }
133
- return undefined;
202
+ // AST has no return type annotation — try JSDoc fallback
203
+ return extractJsDocReturnType(node);
134
204
  }
135
205
  /**
136
206
  * Extract visibility from accessibility_modifier or #private name.
@@ -218,7 +288,14 @@ const shared = {
218
288
  // are not discovered because class_expression is not in typeDeclarationNodes.
219
289
  // - declare module / declare global augmentations — methods inside ambient_module_declaration
220
290
  // wrappers are not surfaced because the top-level walker doesn't descend into them.
221
- methodNodeTypes: ['method_definition', 'method_signature', 'abstract_method_signature'],
291
+ methodNodeTypes: [
292
+ 'method_definition',
293
+ 'method_signature',
294
+ 'abstract_method_signature',
295
+ 'function_declaration',
296
+ 'generator_function_declaration',
297
+ 'function_signature',
298
+ ],
222
299
  bodyNodeTypes: ['class_body', 'interface_body'],
223
300
  extractName(node) {
224
301
  const nameNode = node.childForFieldName('name');
@@ -1,5 +1,11 @@
1
1
  import type { MethodExtractor, MethodExtractionConfig } from '../method-types.js';
2
2
  /**
3
3
  * Create a MethodExtractor from a declarative config.
4
+ *
5
+ * @throws {Error} if `typeDeclarationNodes` contains a static-implying owner
6
+ * type (companion_object / object_declaration / singleton_class) that is
7
+ * not covered by `staticOwnerTypes`. The guard fires once per language at
8
+ * provider construction to prevent silent `isStatic=false` regressions. See
9
+ * `STATIC_IMPLYING_OWNER_TYPES` for the exact opt-out convention.
4
10
  */
5
11
  export declare function createMethodExtractor(config: MethodExtractionConfig): MethodExtractor;
@@ -1,10 +1,53 @@
1
1
  // gitnexus/src/core/ingestion/method-extractors/generic.ts
2
- /** Owner node types where member functions are effectively static (JVM semantics). */
3
- const STATIC_OWNER_TYPES = new Set(['companion_object', 'object_declaration']);
2
+ /**
3
+ * Node types that imply static member semantics when they appear as the owner
4
+ * of a method (Kotlin companion objects, Kotlin top-level `object` declarations,
5
+ * Ruby `class << self` singleton classes). A config that lists any of these in
6
+ * `typeDeclarationNodes` MUST also include the same node type in
7
+ * `staticOwnerTypes` — otherwise methods inside these containers silently get
8
+ * `isStatic=false`, which is a correctness bug that previously only surfaced
9
+ * at analysis time on large repos.
10
+ *
11
+ * Opt-out: a config that sets `staticOwnerTypes: new Set()` (explicit empty
12
+ * set) signals "I handle static-ness entirely via isStatic()" and is exempt
13
+ * from the guard.
14
+ */
15
+ const STATIC_IMPLYING_OWNER_TYPES = new Set([
16
+ 'companion_object',
17
+ 'object_declaration',
18
+ 'singleton_class',
19
+ ]);
4
20
  /**
5
21
  * Create a MethodExtractor from a declarative config.
22
+ *
23
+ * @throws {Error} if `typeDeclarationNodes` contains a static-implying owner
24
+ * type (companion_object / object_declaration / singleton_class) that is
25
+ * not covered by `staticOwnerTypes`. The guard fires once per language at
26
+ * provider construction to prevent silent `isStatic=false` regressions. See
27
+ * `STATIC_IMPLYING_OWNER_TYPES` for the exact opt-out convention.
6
28
  */
7
29
  export function createMethodExtractor(config) {
30
+ // Runtime invariant: each static-implying container type declared in
31
+ // typeDeclarationNodes must be covered by staticOwnerTypes. An explicit
32
+ // empty Set is treated as intentional opt-out.
33
+ if (config.staticOwnerTypes === undefined) {
34
+ const missing = config.typeDeclarationNodes.filter((t) => STATIC_IMPLYING_OWNER_TYPES.has(t));
35
+ if (missing.length > 0) {
36
+ throw new Error(`[MethodExtractionConfig:${config.language}] typeDeclarationNodes includes static-implying owner type(s) ` +
37
+ `${JSON.stringify(missing)} but staticOwnerTypes is not set. Add ` +
38
+ `'staticOwnerTypes: new Set([${missing.map((t) => `'${t}'`).join(', ')}])' ` +
39
+ `to the config, or set 'staticOwnerTypes: new Set()' to opt out explicitly.`);
40
+ }
41
+ }
42
+ else {
43
+ const missing = config.typeDeclarationNodes.filter((t) => STATIC_IMPLYING_OWNER_TYPES.has(t) && !config.staticOwnerTypes.has(t));
44
+ // Explicit empty Set is the opt-out signal; don't second-guess it.
45
+ if (missing.length > 0 && config.staticOwnerTypes.size > 0) {
46
+ throw new Error(`[MethodExtractionConfig:${config.language}] typeDeclarationNodes includes static-implying owner type(s) ` +
47
+ `${JSON.stringify(missing)} that are missing from staticOwnerTypes. ` +
48
+ `Either add them to staticOwnerTypes, or set 'staticOwnerTypes: new Set()' to opt out explicitly.`);
49
+ }
50
+ }
8
51
  const typeDeclarationSet = new Set(config.typeDeclarationNodes);
9
52
  const methodNodeSet = new Set(config.methodNodeTypes);
10
53
  const bodyNodeSet = new Set(config.bodyNodeTypes);
@@ -16,18 +59,26 @@ export function createMethodExtractor(config) {
16
59
  extract(node, context) {
17
60
  if (!typeDeclarationSet.has(node.type))
18
61
  return null;
19
- // Resolve owner name: field-based → type_identifier → simple_identifier → "Companion"
62
+ // Resolve owner name: config hook → field-based → type_identifier → simple_identifier → "Companion"
20
63
  let ownerName;
21
- const nameField = node.childForFieldName('name');
22
- if (nameField) {
23
- ownerName = nameField.text;
64
+ if (config.extractOwnerName) {
65
+ ownerName = config.extractOwnerName(node);
24
66
  }
25
- else {
26
- for (let i = 0; i < node.namedChildCount; i++) {
27
- const child = node.namedChild(i);
28
- if (child && (child.type === 'type_identifier' || child.type === 'simple_identifier')) {
29
- ownerName = child.text;
30
- break;
67
+ if (!ownerName) {
68
+ const nameField = node.childForFieldName('name');
69
+ if (nameField) {
70
+ ownerName = nameField.text;
71
+ }
72
+ else {
73
+ for (let i = 0; i < node.namedChildCount; i++) {
74
+ const child = node.namedChild(i);
75
+ if (child &&
76
+ (child.type === 'type_identifier' ||
77
+ child.type === 'simple_identifier' ||
78
+ child.type === 'identifier')) {
79
+ ownerName = child.text;
80
+ break;
81
+ }
31
82
  }
32
83
  }
33
84
  }
@@ -50,6 +101,12 @@ export function createMethodExtractor(config) {
50
101
  }
51
102
  return { ownerName, methods };
52
103
  },
104
+ extractFromNode(node, context) {
105
+ if (!methodNodeSet.has(node.type))
106
+ return null;
107
+ return buildMethod(node, node, context, config);
108
+ },
109
+ ...(config.extractFunctionName ? { extractFunctionName: config.extractFunctionName } : {}),
53
110
  };
54
111
  }
55
112
  function findBodies(node, bodyNodeSet) {
@@ -77,19 +134,27 @@ function findBodies(node, bodyNodeSet) {
77
134
  }
78
135
  return result;
79
136
  }
80
- function addNestedBodies(parent, bodyNodeSet, out) {
137
+ function addNestedBodies(parent, bodyNodeSet, out, seen) {
138
+ const visited = seen ?? new Set(out);
81
139
  for (let i = 0; i < parent.namedChildCount; i++) {
82
140
  const child = parent.namedChild(i);
83
- if (child && bodyNodeSet.has(child.type) && !out.includes(child)) {
141
+ if (child && bodyNodeSet.has(child.type) && !visited.has(child)) {
142
+ visited.add(child);
84
143
  out.push(child);
85
144
  }
86
145
  }
87
146
  }
88
147
  function extractMethodsFromBody(body, ownerNode, context, config, methodNodeSet, out) {
89
148
  for (let i = 0; i < body.namedChildCount; i++) {
90
- const child = body.namedChild(i);
149
+ let child = body.namedChild(i);
91
150
  if (!child)
92
151
  continue;
152
+ // C++ template methods are wrapped in template_declaration — unwrap to the inner node
153
+ if (child.type === 'template_declaration') {
154
+ const inner = child.namedChildren.find((c) => methodNodeSet.has(c.type));
155
+ if (inner)
156
+ child = inner;
157
+ }
93
158
  if (methodNodeSet.has(child.type)) {
94
159
  const method = buildMethod(child, ownerNode, context, config);
95
160
  if (method)
@@ -115,8 +180,9 @@ function buildMethod(node, ownerNode, context, config) {
115
180
  // Domain invariant: abstract methods cannot be final
116
181
  if (isAbstract)
117
182
  isFinal = false;
118
- // companion_object / object_declaration members are effectively static on JVM
119
- const isStatic = STATIC_OWNER_TYPES.has(ownerNode.type) || config.isStatic(node);
183
+ // Static-owner detection is config-driven: each language declares which
184
+ // container node types imply static (e.g. Ruby singleton_class, Kotlin companion_object).
185
+ const isStatic = (config.staticOwnerTypes?.has(ownerNode.type) ?? false) || config.isStatic(node);
120
186
  return {
121
187
  name,
122
188
  receiverType: config.extractReceiverType?.(node) ?? null,
@@ -130,6 +196,7 @@ function buildMethod(node, ownerNode, context, config) {
130
196
  ...(config.isOverride?.(node) ? { isOverride: true } : {}),
131
197
  ...(config.isAsync?.(node) ? { isAsync: true } : {}),
132
198
  ...(config.isPartial?.(node) ? { isPartial: true } : {}),
199
+ ...(config.isConst?.(node) ? { isConst: true } : {}),
133
200
  annotations: config.extractAnnotations?.(node) ?? [],
134
201
  sourceFile: context.filePath,
135
202
  line: node.startPosition.row + 1,
@@ -5,6 +5,10 @@ export type MethodVisibility = FieldVisibility;
5
5
  export interface ParameterInfo {
6
6
  name: string;
7
7
  type: string | null;
8
+ /** Full type text including generic/template args (e.g. 'vector<int>', 'List<String>').
9
+ * Used by typeTagForId for overload disambiguation where generic args matter.
10
+ * Falls back to `type` when not set. */
11
+ rawType?: string | null;
8
12
  isOptional: boolean;
9
13
  isVariadic: boolean;
10
14
  }
@@ -21,6 +25,7 @@ export interface MethodInfo {
21
25
  isOverride?: boolean;
22
26
  isAsync?: boolean;
23
27
  isPartial?: boolean;
28
+ isConst?: boolean;
24
29
  annotations: string[];
25
30
  sourceFile: string;
26
31
  line: number;
@@ -37,6 +42,17 @@ export interface MethodExtractor {
37
42
  language: SupportedLanguages;
38
43
  extract(node: SyntaxNode, context: MethodExtractorContext): ExtractedMethods | null;
39
44
  isTypeDeclaration(node: SyntaxNode): boolean;
45
+ /** Extract method info from a standalone method node (e.g. Go top-level method_declaration). */
46
+ extractFromNode?(node: SyntaxNode, context: MethodExtractorContext): MethodInfo | null;
47
+ /** Extract function name + label from an AST node during parent-walk.
48
+ * Languages with non-standard AST structures (e.g. C/C++ declarator
49
+ * unwrapping, Swift init/deinit, Rust impl_item) provide this hook
50
+ * to replace the generic name-field lookup.
51
+ * Return null to fall through to the generic extractor. */
52
+ extractFunctionName?(node: SyntaxNode): {
53
+ funcName: string | null;
54
+ label: import('../../_shared/index.js').NodeLabel;
55
+ } | null;
40
56
  }
41
57
  export interface MethodExtractionConfig {
42
58
  language: SupportedLanguages;
@@ -56,6 +72,19 @@ export interface MethodExtractionConfig {
56
72
  isOverride?: (node: SyntaxNode) => boolean;
57
73
  isAsync?: (node: SyntaxNode) => boolean;
58
74
  isPartial?: (node: SyntaxNode) => boolean;
75
+ isConst?: (node: SyntaxNode) => boolean;
76
+ /** Owner node types where member functions are effectively static (e.g.
77
+ * Ruby singleton_class, Kotlin companion_object / object_declaration).
78
+ * When the ownerNode matches one of these types, isStatic is forced true. */
79
+ staticOwnerTypes?: ReadonlySet<string>;
80
+ /** Resolve the owner name from a standalone method node (e.g. Go receiver type). */
81
+ extractOwnerName?: (node: SyntaxNode) => string | undefined;
59
82
  /** Extract a primary constructor from the owner node itself (e.g. C# 12 class Point(int x, int y)). */
60
83
  extractPrimaryConstructor?: (ownerNode: SyntaxNode, context: MethodExtractorContext) => MethodInfo | null;
84
+ /** Extract function name + label from an AST node during parent-walk.
85
+ * Passed through to the MethodExtractor by createMethodExtractor. */
86
+ extractFunctionName?: (node: SyntaxNode) => {
87
+ funcName: string | null;
88
+ label: import('../../_shared/index.js').NodeLabel;
89
+ } | null;
61
90
  }