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,304 @@
1
+ // gitnexus/src/core/ingestion/method-extractors/configs/php.ts
2
+ // Verified against tree-sitter-php 0.23.12
3
+ import { SupportedLanguages } from '../../../../_shared/index.js';
4
+ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
+ // ---------------------------------------------------------------------------
6
+ // PHP helpers
7
+ // ---------------------------------------------------------------------------
8
+ /** Regex to extract PHPDoc @return annotations: `@return User` */
9
+ const PHPDOC_RETURN_RE = /@return\s+(\S+)/;
10
+ /** Node types to skip when walking backwards through siblings for PHPDoc. */
11
+ const PHPDOC_SKIP_NODE_TYPES = new Set(['attribute_list', 'attribute']);
12
+ /**
13
+ * Normalize a PHPDoc return type for the MethodExtractor.
14
+ * Strips nullable prefix, null/false/void unions, namespace prefixes, and
15
+ * rejects uninformative types (mixed, void, self, static, object, array).
16
+ */
17
+ function normalizePhpReturnType(raw) {
18
+ let type = raw.startsWith('?') ? raw.slice(1) : raw;
19
+ const parts = type
20
+ .split('|')
21
+ .filter((p) => p !== 'null' && p !== 'false' && p !== 'void' && p !== 'mixed');
22
+ if (parts.length !== 1)
23
+ return undefined;
24
+ type = parts[0];
25
+ const segments = type.split('\\');
26
+ type = segments[segments.length - 1];
27
+ if (type === 'mixed' ||
28
+ type === 'void' ||
29
+ type === 'self' ||
30
+ type === 'static' ||
31
+ type === 'object' ||
32
+ type === 'array')
33
+ return undefined;
34
+ if (/^\w+(\[\])?$/.test(type) || /^\w+\s*</.test(type))
35
+ return type;
36
+ return undefined;
37
+ }
38
+ /**
39
+ * Walk backwards through preceding siblings of `node` to find a PHPDoc
40
+ * `@return Type` annotation. Skips `attribute_list` nodes (PHP 8 attributes).
41
+ */
42
+ function extractPhpDocReturnType(node) {
43
+ let sibling = node.previousSibling;
44
+ while (sibling) {
45
+ if (sibling.type === 'comment') {
46
+ const match = PHPDOC_RETURN_RE.exec(sibling.text);
47
+ if (match)
48
+ return normalizePhpReturnType(match[1]);
49
+ }
50
+ else if (sibling.isNamed && !PHPDOC_SKIP_NODE_TYPES.has(sibling.type)) {
51
+ break;
52
+ }
53
+ sibling = sibling.previousSibling;
54
+ }
55
+ return undefined;
56
+ }
57
+ const PHP_VIS = new Set(['public', 'private', 'protected']);
58
+ /**
59
+ * Find the visibility keyword from a visibility_modifier named child.
60
+ * PHP tree-sitter emits `visibility_modifier` as a named node with text
61
+ * "public", "private", or "protected".
62
+ */
63
+ function findPhpVisibility(node) {
64
+ for (let i = 0; i < node.namedChildCount; i++) {
65
+ const child = node.namedChild(i);
66
+ if (child?.type === 'visibility_modifier') {
67
+ const text = child.text.trim();
68
+ if (PHP_VIS.has(text))
69
+ return text;
70
+ }
71
+ }
72
+ return 'public'; // PHP methods are public by default
73
+ }
74
+ /**
75
+ * Check for a named modifier child of a specific type.
76
+ * PHP tree-sitter uses distinct node types: abstract_modifier, final_modifier,
77
+ * static_modifier — rather than a wrapper `modifiers` node with keyword children.
78
+ */
79
+ function hasModifierNode(node, modifierType) {
80
+ for (let i = 0; i < node.namedChildCount; i++) {
81
+ const child = node.namedChild(i);
82
+ if (child?.type === modifierType)
83
+ return true;
84
+ }
85
+ return false;
86
+ }
87
+ /**
88
+ * Extract the return type from a PHP method_declaration node.
89
+ *
90
+ * In tree-sitter-php, the return type is not exposed via a named field.
91
+ * It appears as a type node (primitive_type, named_type, union_type,
92
+ * optional_type, nullable_type, intersection_type) after the formal_parameters
93
+ * and a `:` token separator.
94
+ *
95
+ * When the AST return type is missing or uninformative (`array` / `iterable`),
96
+ * falls back to parsing PHPDoc `@return Type` from preceding doc comments.
97
+ */
98
+ function extractPhpReturnType(node) {
99
+ const TYPE_NODE_TYPES = new Set([
100
+ 'primitive_type',
101
+ 'named_type',
102
+ 'union_type',
103
+ 'optional_type',
104
+ 'nullable_type',
105
+ 'intersection_type',
106
+ ]);
107
+ let astType;
108
+ let seenParams = false;
109
+ for (let i = 0; i < node.childCount; i++) {
110
+ const child = node.child(i);
111
+ if (!child)
112
+ continue;
113
+ if (child.type === 'formal_parameters') {
114
+ seenParams = true;
115
+ continue;
116
+ }
117
+ // After the parameters node, look for the colon and then the type
118
+ if (seenParams && child.isNamed && TYPE_NODE_TYPES.has(child.type)) {
119
+ astType = child.text?.trim();
120
+ break;
121
+ }
122
+ // Stop at body or semicolon
123
+ if (child.type === 'compound_statement' || (!child.isNamed && child.text === ';')) {
124
+ break;
125
+ }
126
+ }
127
+ // If AST type is missing or uninformative, try PHPDoc @return fallback
128
+ if (!astType || astType === 'array' || astType === 'iterable') {
129
+ const docType = extractPhpDocReturnType(node);
130
+ if (docType)
131
+ return docType;
132
+ }
133
+ return astType;
134
+ }
135
+ /**
136
+ * Extract parameters from a PHP method_declaration node.
137
+ *
138
+ * PHP parameter types in tree-sitter-php:
139
+ * - `simple_parameter`: regular parameter with optional type and default
140
+ * - `variadic_parameter`: `...$param` with optional type
141
+ * - `property_promotion_parameter`: constructor promotion `private string $name`
142
+ * (may also be variadic via an ERROR node containing `...`)
143
+ */
144
+ function extractPhpParameters(node) {
145
+ const paramList = node.childForFieldName('parameters');
146
+ if (!paramList)
147
+ return [];
148
+ const params = [];
149
+ for (let i = 0; i < paramList.namedChildCount; i++) {
150
+ const param = paramList.namedChild(i);
151
+ if (!param)
152
+ continue;
153
+ if (param.type === 'simple_parameter') {
154
+ const nameNode = param.childForFieldName('name');
155
+ if (!nameNode)
156
+ continue;
157
+ const typeNode = param.childForFieldName('type');
158
+ const typeName = typeNode ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim()) : null;
159
+ // Detect optional: '=' token among children indicates a default value
160
+ let isOptional = false;
161
+ for (let j = 0; j < param.childCount; j++) {
162
+ const c = param.child(j);
163
+ if (c && !c.isNamed && c.text === '=') {
164
+ isOptional = true;
165
+ break;
166
+ }
167
+ }
168
+ params.push({
169
+ name: stripDollar(nameNode.text),
170
+ type: typeName ?? null,
171
+ rawType: typeNode?.text?.trim() ?? null,
172
+ isOptional,
173
+ isVariadic: false,
174
+ });
175
+ }
176
+ else if (param.type === 'variadic_parameter') {
177
+ const nameNode = param.childForFieldName('name');
178
+ if (!nameNode)
179
+ continue;
180
+ const typeNode = param.childForFieldName('type');
181
+ const typeName = typeNode ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim()) : null;
182
+ params.push({
183
+ name: stripDollar(nameNode.text),
184
+ type: typeName ?? null,
185
+ rawType: typeNode?.text?.trim() ?? null,
186
+ isOptional: false,
187
+ isVariadic: true,
188
+ });
189
+ }
190
+ else if (param.type === 'property_promotion_parameter') {
191
+ const nameNode = param.childForFieldName('name');
192
+ if (!nameNode)
193
+ continue;
194
+ const typeNode = param.childForFieldName('type');
195
+ const typeName = typeNode ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim()) : null;
196
+ // Detect variadic: an ERROR child containing "..." indicates variadic promotion
197
+ let isVariadic = false;
198
+ for (let j = 0; j < param.childCount; j++) {
199
+ const c = param.child(j);
200
+ if (c && (c.text === '...' || (c.type === 'ERROR' && c.text === '...'))) {
201
+ isVariadic = true;
202
+ break;
203
+ }
204
+ }
205
+ params.push({
206
+ name: stripDollar(nameNode.text),
207
+ type: typeName ?? null,
208
+ rawType: typeNode?.text?.trim() ?? null,
209
+ isOptional: false,
210
+ isVariadic,
211
+ });
212
+ }
213
+ }
214
+ return params;
215
+ }
216
+ /** Strip leading $ from PHP variable names. */
217
+ function stripDollar(name) {
218
+ return name.startsWith('$') ? name.slice(1) : name;
219
+ }
220
+ /**
221
+ * Extract PHP 8 attributes (#[...]) from a method_declaration node.
222
+ *
223
+ * AST structure: attribute_list → attribute_group → attribute → name child.
224
+ * Names are prefixed with '#' to distinguish from Java/Kotlin @ annotations.
225
+ */
226
+ function extractPhpAnnotations(node) {
227
+ const annotations = [];
228
+ for (let i = 0; i < node.namedChildCount; i++) {
229
+ const child = node.namedChild(i);
230
+ if (!child || child.type !== 'attribute_list')
231
+ continue;
232
+ for (let j = 0; j < child.namedChildCount; j++) {
233
+ const group = child.namedChild(j);
234
+ if (!group || group.type !== 'attribute_group')
235
+ continue;
236
+ for (let k = 0; k < group.namedChildCount; k++) {
237
+ const attr = group.namedChild(k);
238
+ if (!attr || attr.type !== 'attribute')
239
+ continue;
240
+ const nameNode = attr.firstNamedChild;
241
+ if (nameNode && nameNode.type === 'name') {
242
+ annotations.push('#' + nameNode.text);
243
+ }
244
+ }
245
+ }
246
+ }
247
+ return annotations;
248
+ }
249
+ // ---------------------------------------------------------------------------
250
+ // PHP config
251
+ // ---------------------------------------------------------------------------
252
+ export const phpMethodConfig = {
253
+ language: SupportedLanguages.PHP,
254
+ typeDeclarationNodes: [
255
+ 'class_declaration',
256
+ 'interface_declaration',
257
+ 'trait_declaration',
258
+ 'enum_declaration',
259
+ ],
260
+ methodNodeTypes: ['method_declaration', 'function_definition'],
261
+ bodyNodeTypes: ['declaration_list'],
262
+ extractName(node) {
263
+ return node.childForFieldName('name')?.text;
264
+ },
265
+ extractReturnType: extractPhpReturnType,
266
+ extractParameters: extractPhpParameters,
267
+ extractVisibility: findPhpVisibility,
268
+ isStatic(node) {
269
+ return hasModifierNode(node, 'static_modifier');
270
+ },
271
+ isAbstract(node, ownerNode) {
272
+ if (hasModifierNode(node, 'abstract_modifier'))
273
+ return true;
274
+ // Interface methods are implicitly abstract when they have no body.
275
+ // Check ownerNode first, then fall back to walking the parent chain
276
+ // (needed when called from extractFromNode where ownerNode === node).
277
+ let isInterface = ownerNode.type === 'interface_declaration';
278
+ if (!isInterface) {
279
+ let p = node.parent;
280
+ while (p) {
281
+ if (p.type === 'interface_declaration') {
282
+ isInterface = true;
283
+ break;
284
+ }
285
+ p = p.parent;
286
+ }
287
+ }
288
+ if (isInterface) {
289
+ const body = node.childForFieldName('body');
290
+ if (body)
291
+ return false;
292
+ for (let i = 0; i < node.namedChildCount; i++) {
293
+ if (node.namedChild(i)?.type === 'compound_statement')
294
+ return false;
295
+ }
296
+ return true;
297
+ }
298
+ return false;
299
+ },
300
+ isFinal(node) {
301
+ return hasModifierNode(node, 'final_modifier');
302
+ },
303
+ extractAnnotations: extractPhpAnnotations,
304
+ };
@@ -0,0 +1,2 @@
1
+ import type { MethodExtractionConfig } from '../../method-types.js';
2
+ export declare const pythonMethodConfig: MethodExtractionConfig;
@@ -0,0 +1,309 @@
1
+ // gitnexus/src/core/ingestion/method-extractors/configs/python.ts
2
+ // Verified against tree-sitter-python 0.23.4
3
+ import { SupportedLanguages } from '../../../../_shared/index.js';
4
+ import { hasKeyword } from '../../field-extractors/configs/helpers.js';
5
+ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
6
+ // ---------------------------------------------------------------------------
7
+ // Python helpers
8
+ // ---------------------------------------------------------------------------
9
+ /** Names that represent the instance/class receiver — not real parameters. */
10
+ const SELF_NAMES = new Set(['self', 'cls']);
11
+ /**
12
+ * Unwrap a decorated_definition to its inner function_definition.
13
+ *
14
+ * tree-sitter-python wraps decorated functions/methods in a `decorated_definition`
15
+ * node that contains the decorators as children followed by the function_definition.
16
+ * This is different from TS/JS where decorators are siblings.
17
+ */
18
+ function unwrapDecorated(node) {
19
+ if (node.type === 'decorated_definition') {
20
+ for (let i = 0; i < node.namedChildCount; i++) {
21
+ const child = node.namedChild(i);
22
+ if (child && child.type === 'function_definition')
23
+ return child;
24
+ }
25
+ }
26
+ return node;
27
+ }
28
+ /**
29
+ * Collect decorator names from a decorated_definition wrapper.
30
+ *
31
+ * Returns decorator names prefixed with '@'. If the node is a plain
32
+ * function_definition (no decorators), check if its parent is a
33
+ * decorated_definition and collect from there.
34
+ */
35
+ function collectDecorators(node) {
36
+ let wrapper = null;
37
+ if (node.type === 'decorated_definition') {
38
+ wrapper = node;
39
+ }
40
+ else if (node.parent?.type === 'decorated_definition') {
41
+ wrapper = node.parent;
42
+ }
43
+ if (!wrapper)
44
+ return [];
45
+ const decorators = [];
46
+ for (let i = 0; i < wrapper.namedChildCount; i++) {
47
+ const child = wrapper.namedChild(i);
48
+ if (child && child.type === 'decorator') {
49
+ decorators.push(child);
50
+ }
51
+ }
52
+ return decorators;
53
+ }
54
+ function extractDecoratorName(decorator) {
55
+ // decorator > identifier (simple)
56
+ // decorator > call > identifier (call-style, e.g. @lru_cache())
57
+ // decorator > attribute (dotted, e.g. @abc.abstractmethod)
58
+ const expr = decorator.firstNamedChild;
59
+ if (!expr)
60
+ return undefined;
61
+ if (expr.type === 'identifier')
62
+ return '@' + expr.text;
63
+ if (expr.type === 'attribute')
64
+ return '@' + expr.text;
65
+ if (expr.type === 'call') {
66
+ const fn = expr.childForFieldName('function');
67
+ return fn ? '@' + fn.text : undefined;
68
+ }
69
+ return undefined;
70
+ }
71
+ function hasDecorator(node, name) {
72
+ const decorators = collectDecorators(node);
73
+ for (const dec of decorators) {
74
+ const decName = extractDecoratorName(dec);
75
+ if (decName === '@' + name || decName?.endsWith('.' + name))
76
+ return true;
77
+ }
78
+ return false;
79
+ }
80
+ /**
81
+ * Extract parameters from a Python function_definition.
82
+ *
83
+ * Handles: identifier, default_parameter, typed_parameter, typed_default_parameter,
84
+ * list_splat_pattern (*args), dictionary_splat_pattern (**kwargs), and typed variants.
85
+ * Skips `self` and `cls` first parameters.
86
+ */
87
+ function extractPythonParameters(node) {
88
+ const funcNode = unwrapDecorated(node);
89
+ const paramList = funcNode.childForFieldName('parameters');
90
+ if (!paramList)
91
+ return [];
92
+ const params = [];
93
+ let isFirst = true;
94
+ for (let i = 0; i < paramList.namedChildCount; i++) {
95
+ const param = paramList.namedChild(i);
96
+ if (!param)
97
+ continue;
98
+ switch (param.type) {
99
+ case 'identifier': {
100
+ // Bare parameter: `self`, `cls`, or untyped `x`
101
+ if (isFirst && SELF_NAMES.has(param.text)) {
102
+ isFirst = false;
103
+ continue;
104
+ }
105
+ isFirst = false;
106
+ params.push({
107
+ name: param.text,
108
+ type: null,
109
+ rawType: null,
110
+ isOptional: false,
111
+ isVariadic: false,
112
+ });
113
+ break;
114
+ }
115
+ case 'default_parameter': {
116
+ // `x = value` — untyped with default
117
+ isFirst = false;
118
+ const nameNode = param.childForFieldName('name');
119
+ if (nameNode) {
120
+ params.push({
121
+ name: nameNode.text,
122
+ type: null,
123
+ rawType: null,
124
+ isOptional: true,
125
+ isVariadic: false,
126
+ });
127
+ }
128
+ break;
129
+ }
130
+ case 'typed_parameter': {
131
+ // `x: int` or `*args: str` or `**kwargs: int`
132
+ // The first named child can be identifier, list_splat_pattern, or dictionary_splat_pattern
133
+ const inner = param.firstNamedChild;
134
+ if (!inner)
135
+ break;
136
+ if (isFirst && inner.type === 'identifier' && SELF_NAMES.has(inner.text)) {
137
+ isFirst = false;
138
+ continue;
139
+ }
140
+ isFirst = false;
141
+ const typeNode = param.childForFieldName('type');
142
+ const typeText = typeNode
143
+ ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
144
+ : null;
145
+ const rawTypeText = typeNode?.text?.trim() ?? null;
146
+ if (inner.type === 'list_splat_pattern') {
147
+ const nameId = inner.firstNamedChild;
148
+ if (nameId) {
149
+ params.push({
150
+ name: nameId.text,
151
+ type: typeText,
152
+ rawType: rawTypeText,
153
+ isOptional: false,
154
+ isVariadic: true,
155
+ });
156
+ }
157
+ }
158
+ else if (inner.type === 'dictionary_splat_pattern') {
159
+ const nameId = inner.firstNamedChild;
160
+ if (nameId) {
161
+ params.push({
162
+ name: nameId.text,
163
+ type: typeText,
164
+ rawType: rawTypeText,
165
+ isOptional: false,
166
+ isVariadic: true,
167
+ });
168
+ }
169
+ }
170
+ else {
171
+ params.push({
172
+ name: inner.text,
173
+ type: typeText,
174
+ rawType: rawTypeText,
175
+ isOptional: false,
176
+ isVariadic: false,
177
+ });
178
+ }
179
+ break;
180
+ }
181
+ case 'typed_default_parameter': {
182
+ // `x: int = 5` — typed with default
183
+ isFirst = false;
184
+ const nameNode = param.childForFieldName('name');
185
+ const typeNode = param.childForFieldName('type');
186
+ if (nameNode) {
187
+ params.push({
188
+ name: nameNode.text,
189
+ type: typeNode
190
+ ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
191
+ : null,
192
+ rawType: typeNode?.text?.trim() ?? null,
193
+ isOptional: true,
194
+ isVariadic: false,
195
+ });
196
+ }
197
+ break;
198
+ }
199
+ case 'list_splat_pattern': {
200
+ // `*args` (untyped)
201
+ isFirst = false;
202
+ const nameId = param.firstNamedChild;
203
+ if (nameId) {
204
+ params.push({
205
+ name: nameId.text,
206
+ type: null,
207
+ rawType: null,
208
+ isOptional: false,
209
+ isVariadic: true,
210
+ });
211
+ }
212
+ break;
213
+ }
214
+ case 'dictionary_splat_pattern': {
215
+ // `**kwargs` (untyped)
216
+ isFirst = false;
217
+ const nameId = param.firstNamedChild;
218
+ if (nameId) {
219
+ params.push({
220
+ name: nameId.text,
221
+ type: null,
222
+ rawType: null,
223
+ isOptional: false,
224
+ isVariadic: true,
225
+ });
226
+ }
227
+ break;
228
+ }
229
+ default:
230
+ isFirst = false;
231
+ break;
232
+ }
233
+ }
234
+ return params;
235
+ }
236
+ /**
237
+ * Extract return type from the `return_type` field.
238
+ *
239
+ * tree-sitter-python uses a `type` field on function_definition for the return
240
+ * type annotation (e.g. `-> str`). The field contains a type node.
241
+ */
242
+ function extractPythonReturnType(node) {
243
+ const funcNode = unwrapDecorated(node);
244
+ const returnType = funcNode.childForFieldName('return_type');
245
+ if (!returnType)
246
+ return undefined;
247
+ // Use .text to preserve full generic types (e.g. list[User], Dict[str, User])
248
+ // that the call resolver needs for for-loop iterable and return-type inference.
249
+ return returnType.text?.trim();
250
+ }
251
+ /**
252
+ * Extract visibility based on Python name-mangling convention.
253
+ * `__name` (not dunder) = private, `_name` = protected, else public.
254
+ */
255
+ function extractPythonVisibility(node) {
256
+ const funcNode = unwrapDecorated(node);
257
+ const nameNode = funcNode.childForFieldName('name');
258
+ const name = nameNode?.text;
259
+ if (!name)
260
+ return 'public';
261
+ if (name.startsWith('__') && !name.endsWith('__'))
262
+ return 'private';
263
+ if (name.startsWith('_') && !(name.startsWith('__') && name.endsWith('__')))
264
+ return 'protected';
265
+ return 'public';
266
+ }
267
+ // ---------------------------------------------------------------------------
268
+ // Config
269
+ // ---------------------------------------------------------------------------
270
+ export const pythonMethodConfig = {
271
+ language: SupportedLanguages.Python,
272
+ typeDeclarationNodes: ['class_definition'],
273
+ // Both function_definition and decorated_definition must be listed:
274
+ // decorated methods appear as decorated_definition in the class body block,
275
+ // while undecorated methods appear as function_definition directly.
276
+ methodNodeTypes: ['function_definition', 'decorated_definition'],
277
+ bodyNodeTypes: ['block'],
278
+ extractName(node) {
279
+ const funcNode = unwrapDecorated(node);
280
+ const nameNode = funcNode.childForFieldName('name');
281
+ return nameNode?.text;
282
+ },
283
+ extractReturnType: extractPythonReturnType,
284
+ extractParameters: extractPythonParameters,
285
+ extractVisibility: extractPythonVisibility,
286
+ isStatic(node) {
287
+ return hasDecorator(node, 'staticmethod') || hasDecorator(node, 'classmethod');
288
+ },
289
+ isAbstract(node, _ownerNode) {
290
+ return hasDecorator(node, 'abstractmethod');
291
+ },
292
+ isFinal(_node) {
293
+ return false; // @typing.final (PEP 591) is captured in annotations; isFinal not modeled
294
+ },
295
+ extractAnnotations(node) {
296
+ const decorators = collectDecorators(node);
297
+ const annotations = [];
298
+ for (const dec of decorators) {
299
+ const name = extractDecoratorName(dec);
300
+ if (name)
301
+ annotations.push(name);
302
+ }
303
+ return annotations;
304
+ },
305
+ isAsync(node) {
306
+ const funcNode = unwrapDecorated(node);
307
+ return hasKeyword(funcNode, 'async');
308
+ },
309
+ };
@@ -0,0 +1,2 @@
1
+ import type { MethodExtractionConfig } from '../../method-types.js';
2
+ export declare const rubyMethodConfig: MethodExtractionConfig;