gitnexus 1.5.2 → 1.6.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 (207) 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 +2 -1
  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/cli/wiki.js +15 -44
  31. package/dist/config/ignore-service.js +8 -3
  32. package/dist/core/augmentation/engine.js +1 -1
  33. package/dist/core/git-staleness.d.ts +13 -0
  34. package/dist/core/git-staleness.js +29 -0
  35. package/dist/core/group/bridge-db.d.ts +82 -0
  36. package/dist/core/group/bridge-db.js +460 -0
  37. package/dist/core/group/bridge-schema.d.ts +27 -0
  38. package/dist/core/group/bridge-schema.js +55 -0
  39. package/dist/core/group/config-parser.d.ts +3 -0
  40. package/dist/core/group/config-parser.js +83 -0
  41. package/dist/core/group/contract-extractor.d.ts +7 -0
  42. package/dist/core/group/contract-extractor.js +1 -0
  43. package/dist/core/group/extractors/grpc-extractor.d.ts +16 -0
  44. package/dist/core/group/extractors/grpc-extractor.js +264 -0
  45. package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
  46. package/dist/core/group/extractors/http-route-extractor.js +428 -0
  47. package/dist/core/group/extractors/topic-extractor.d.ts +9 -0
  48. package/dist/core/group/extractors/topic-extractor.js +234 -0
  49. package/dist/core/group/matching.d.ts +13 -0
  50. package/dist/core/group/matching.js +198 -0
  51. package/dist/core/group/normalization.d.ts +3 -0
  52. package/dist/core/group/normalization.js +115 -0
  53. package/dist/core/group/service-boundary-detector.d.ts +8 -0
  54. package/dist/core/group/service-boundary-detector.js +155 -0
  55. package/dist/core/group/service.d.ts +46 -0
  56. package/dist/core/group/service.js +160 -0
  57. package/dist/core/group/storage.d.ts +9 -0
  58. package/dist/core/group/storage.js +91 -0
  59. package/dist/core/group/sync.d.ts +21 -0
  60. package/dist/core/group/sync.js +148 -0
  61. package/dist/core/group/types.d.ts +130 -0
  62. package/dist/core/group/types.js +1 -0
  63. package/dist/core/ingestion/binding-accumulator.d.ts +207 -0
  64. package/dist/core/ingestion/binding-accumulator.js +332 -0
  65. package/dist/core/ingestion/call-processor.d.ts +155 -24
  66. package/dist/core/ingestion/call-processor.js +1129 -247
  67. package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
  68. package/dist/core/ingestion/class-extractors/generic.js +135 -0
  69. package/dist/core/ingestion/class-types.d.ts +34 -0
  70. package/dist/core/ingestion/class-types.js +1 -0
  71. package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
  72. package/dist/core/ingestion/entry-point-scoring.js +1 -0
  73. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +5 -1
  74. package/dist/core/ingestion/field-extractors/configs/helpers.js +13 -3
  75. package/dist/core/ingestion/field-types.d.ts +2 -2
  76. package/dist/core/ingestion/filesystem-walker.js +8 -0
  77. package/dist/core/ingestion/framework-detection.d.ts +1 -0
  78. package/dist/core/ingestion/framework-detection.js +1 -0
  79. package/dist/core/ingestion/heritage-processor.d.ts +8 -15
  80. package/dist/core/ingestion/heritage-processor.js +15 -28
  81. package/dist/core/ingestion/import-processor.d.ts +1 -11
  82. package/dist/core/ingestion/import-processor.js +0 -12
  83. package/dist/core/ingestion/import-resolvers/utils.js +1 -0
  84. package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
  85. package/dist/core/ingestion/import-resolvers/vue.js +9 -0
  86. package/dist/core/ingestion/language-provider.d.ts +6 -3
  87. package/dist/core/ingestion/languages/c-cpp.js +168 -1
  88. package/dist/core/ingestion/languages/csharp.js +20 -0
  89. package/dist/core/ingestion/languages/dart.js +26 -4
  90. package/dist/core/ingestion/languages/go.js +22 -0
  91. package/dist/core/ingestion/languages/index.d.ts +1 -0
  92. package/dist/core/ingestion/languages/index.js +2 -0
  93. package/dist/core/ingestion/languages/java.js +17 -0
  94. package/dist/core/ingestion/languages/kotlin.js +24 -1
  95. package/dist/core/ingestion/languages/php.js +23 -11
  96. package/dist/core/ingestion/languages/python.js +9 -0
  97. package/dist/core/ingestion/languages/ruby.js +28 -0
  98. package/dist/core/ingestion/languages/rust.js +38 -0
  99. package/dist/core/ingestion/languages/swift.js +31 -0
  100. package/dist/core/ingestion/languages/typescript.d.ts +1 -0
  101. package/dist/core/ingestion/languages/typescript.js +54 -1
  102. package/dist/core/ingestion/languages/vue.d.ts +13 -0
  103. package/dist/core/ingestion/languages/vue.js +81 -0
  104. package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
  105. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
  106. package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
  107. package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
  108. package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
  109. package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
  110. package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
  111. package/dist/core/ingestion/method-extractors/configs/jvm.js +13 -4
  112. package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
  113. package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
  114. package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
  115. package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
  116. package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
  117. package/dist/core/ingestion/method-extractors/configs/ruby.js +285 -0
  118. package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
  119. package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
  120. package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
  121. package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
  122. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.d.ts +3 -0
  123. package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +338 -0
  124. package/dist/core/ingestion/method-extractors/generic.js +38 -15
  125. package/dist/core/ingestion/method-types.d.ts +25 -0
  126. package/dist/core/ingestion/model/field-registry.d.ts +18 -0
  127. package/dist/core/ingestion/model/field-registry.js +22 -0
  128. package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
  129. package/dist/core/ingestion/model/heritage-map.js +159 -0
  130. package/dist/core/ingestion/model/index.d.ts +20 -0
  131. package/dist/core/ingestion/model/index.js +41 -0
  132. package/dist/core/ingestion/model/method-registry.d.ts +62 -0
  133. package/dist/core/ingestion/model/method-registry.js +130 -0
  134. package/dist/core/ingestion/model/registration-table.d.ts +139 -0
  135. package/dist/core/ingestion/model/registration-table.js +224 -0
  136. package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
  137. package/dist/core/ingestion/model/resolution-context.js +337 -0
  138. package/dist/core/ingestion/model/resolve.d.ts +56 -0
  139. package/dist/core/ingestion/model/resolve.js +242 -0
  140. package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
  141. package/dist/core/ingestion/model/semantic-model.js +120 -0
  142. package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
  143. package/dist/core/ingestion/model/symbol-table.js +206 -0
  144. package/dist/core/ingestion/model/type-registry.d.ts +39 -0
  145. package/dist/core/ingestion/model/type-registry.js +62 -0
  146. package/dist/core/ingestion/mro-processor.d.ts +4 -3
  147. package/dist/core/ingestion/mro-processor.js +310 -106
  148. package/dist/core/ingestion/parsing-processor.d.ts +5 -4
  149. package/dist/core/ingestion/parsing-processor.js +210 -85
  150. package/dist/core/ingestion/pipeline.d.ts +2 -0
  151. package/dist/core/ingestion/pipeline.js +192 -68
  152. package/dist/core/ingestion/tree-sitter-queries.d.ts +6 -6
  153. package/dist/core/ingestion/tree-sitter-queries.js +37 -0
  154. package/dist/core/ingestion/type-env.d.ts +15 -2
  155. package/dist/core/ingestion/type-env.js +163 -102
  156. package/dist/core/ingestion/type-extractors/csharp.js +17 -0
  157. package/dist/core/ingestion/type-extractors/jvm.js +11 -0
  158. package/dist/core/ingestion/type-extractors/php.js +0 -55
  159. package/dist/core/ingestion/type-extractors/ruby.js +0 -32
  160. package/dist/core/ingestion/type-extractors/swift.js +13 -0
  161. package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
  162. package/dist/core/ingestion/type-extractors/typescript.js +66 -69
  163. package/dist/core/ingestion/utils/ast-helpers.d.ts +33 -43
  164. package/dist/core/ingestion/utils/ast-helpers.js +129 -565
  165. package/dist/core/ingestion/utils/method-props.d.ts +32 -0
  166. package/dist/core/ingestion/utils/method-props.js +147 -0
  167. package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
  168. package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
  169. package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
  170. package/dist/core/ingestion/workers/parse-worker.js +463 -198
  171. package/dist/core/lbug/lbug-adapter.d.ts +6 -0
  172. package/dist/core/lbug/lbug-adapter.js +68 -3
  173. package/dist/core/lbug/pool-adapter.d.ts +76 -0
  174. package/dist/core/lbug/pool-adapter.js +522 -0
  175. package/dist/core/run-analyze.d.ts +2 -0
  176. package/dist/core/run-analyze.js +1 -1
  177. package/dist/core/search/bm25-index.js +1 -1
  178. package/dist/core/tree-sitter/parser-loader.js +1 -0
  179. package/dist/core/wiki/graph-queries.js +1 -1
  180. package/dist/core/wiki/html-viewer.js +6 -4
  181. package/dist/core/wiki/llm-client.js +4 -6
  182. package/dist/mcp/core/embedder.js +6 -5
  183. package/dist/mcp/core/lbug-adapter.d.ts +3 -63
  184. package/dist/mcp/core/lbug-adapter.js +3 -484
  185. package/dist/mcp/local/local-backend.d.ts +31 -2
  186. package/dist/mcp/local/local-backend.js +255 -46
  187. package/dist/mcp/resources.js +5 -4
  188. package/dist/mcp/staleness.d.ts +3 -13
  189. package/dist/mcp/staleness.js +2 -31
  190. package/dist/mcp/tools.js +80 -4
  191. package/dist/server/analyze-job.d.ts +2 -0
  192. package/dist/server/analyze-job.js +4 -0
  193. package/dist/server/api.d.ts +20 -1
  194. package/dist/server/api.js +306 -71
  195. package/dist/server/git-clone.d.ts +2 -1
  196. package/dist/server/git-clone.js +98 -5
  197. package/dist/storage/git.d.ts +13 -0
  198. package/dist/storage/git.js +25 -0
  199. package/dist/storage/repo-manager.js +1 -1
  200. package/package.json +8 -2
  201. package/scripts/patch-tree-sitter-swift.cjs +78 -0
  202. package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
  203. package/dist/core/ingestion/named-binding-processor.js +0 -42
  204. package/dist/core/ingestion/resolution-context.d.ts +0 -58
  205. package/dist/core/ingestion/resolution-context.js +0 -135
  206. package/dist/core/ingestion/symbol-table.d.ts +0 -79
  207. 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
+ };
@@ -0,0 +1,3 @@
1
+ import type { MethodExtractionConfig } from '../../method-types.js';
2
+ export declare const typescriptMethodConfig: MethodExtractionConfig;
3
+ export declare const javascriptMethodConfig: MethodExtractionConfig;
@@ -0,0 +1,338 @@
1
+ // gitnexus/src/core/ingestion/method-extractors/configs/typescript-javascript.ts
2
+ // Verified against tree-sitter-typescript ^0.23.2, tree-sitter-javascript ^0.23.0
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
+ // TS/JS helpers
8
+ // ---------------------------------------------------------------------------
9
+ const VISIBILITY_KEYWORDS = new Set(['public', 'private', 'protected']);
10
+ /**
11
+ * Extract parameters from formal_parameters.
12
+ *
13
+ * Handles both TS node types (required_parameter, optional_parameter, rest_parameter)
14
+ * and JS node types (identifier, assignment_pattern, rest_pattern), plus destructured
15
+ * parameters (object_pattern, array_pattern) in both grammars.
16
+ */
17
+ function extractTsJsParameters(node) {
18
+ const paramList = node.childForFieldName('parameters');
19
+ if (!paramList)
20
+ return [];
21
+ const params = [];
22
+ for (let i = 0; i < paramList.namedChildCount; i++) {
23
+ const param = paramList.namedChild(i);
24
+ if (!param)
25
+ continue;
26
+ switch (param.type) {
27
+ case 'required_parameter': {
28
+ const patternNode = param.childForFieldName('pattern');
29
+ if (!patternNode)
30
+ break;
31
+ // Skip TS `this` parameter — it's a compile-time type constraint, not a real param
32
+ if (patternNode.type === 'this')
33
+ break;
34
+ // Rest parameter: pattern is a rest_pattern (...args) — extract inner identifier
35
+ const isRest = patternNode.type === 'rest_pattern';
36
+ const nameNode = isRest ? patternNode.firstNamedChild : patternNode;
37
+ if (!nameNode)
38
+ break;
39
+ // type field is a type_annotation — unwrap to get the inner type node
40
+ const typeAnnotation = param.childForFieldName('type');
41
+ const typeNode = typeAnnotation?.firstNamedChild;
42
+ // Default value: presence of a 'value' field means isOptional
43
+ const hasDefault = !!param.childForFieldName('value');
44
+ params.push({
45
+ name: nameNode.text,
46
+ type: typeNode
47
+ ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
48
+ : null,
49
+ rawType: typeNode?.text?.trim() ?? null,
50
+ isOptional: hasDefault,
51
+ isVariadic: isRest,
52
+ });
53
+ break;
54
+ }
55
+ case 'optional_parameter': {
56
+ const nameNode = param.childForFieldName('pattern');
57
+ if (!nameNode)
58
+ break;
59
+ const typeAnnotation = param.childForFieldName('type');
60
+ const typeNode = typeAnnotation?.firstNamedChild;
61
+ params.push({
62
+ name: nameNode.text,
63
+ type: typeNode
64
+ ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
65
+ : null,
66
+ rawType: typeNode?.text?.trim() ?? null,
67
+ isOptional: true,
68
+ isVariadic: false,
69
+ });
70
+ break;
71
+ }
72
+ case 'rest_parameter': {
73
+ const nameNode = param.childForFieldName('pattern');
74
+ if (!nameNode)
75
+ break;
76
+ const typeAnnotation = param.childForFieldName('type');
77
+ const typeNode = typeAnnotation?.firstNamedChild;
78
+ params.push({
79
+ name: nameNode.text,
80
+ type: typeNode
81
+ ? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
82
+ : null,
83
+ rawType: typeNode?.text?.trim() ?? null,
84
+ isOptional: false,
85
+ isVariadic: true,
86
+ });
87
+ break;
88
+ }
89
+ case 'identifier': {
90
+ // JS: bare parameter name, no type info
91
+ params.push({
92
+ name: param.text,
93
+ type: null,
94
+ rawType: null,
95
+ isOptional: false,
96
+ isVariadic: false,
97
+ });
98
+ break;
99
+ }
100
+ case 'assignment_pattern': {
101
+ // JS: param = defaultValue — the left side is the name, isOptional = true
102
+ const left = param.childForFieldName('left');
103
+ if (left) {
104
+ params.push({
105
+ name: left.text,
106
+ type: null,
107
+ rawType: null,
108
+ isOptional: true,
109
+ isVariadic: false,
110
+ });
111
+ }
112
+ break;
113
+ }
114
+ case 'rest_pattern': {
115
+ // JS: ...args
116
+ const inner = param.firstNamedChild;
117
+ if (inner) {
118
+ params.push({
119
+ name: inner.text,
120
+ type: null,
121
+ rawType: null,
122
+ isOptional: false,
123
+ isVariadic: true,
124
+ });
125
+ }
126
+ break;
127
+ }
128
+ case 'object_pattern':
129
+ case 'array_pattern': {
130
+ // Destructured parameter — use full text as name
131
+ params.push({
132
+ name: param.text,
133
+ type: null,
134
+ rawType: null,
135
+ isOptional: false,
136
+ isVariadic: false,
137
+ });
138
+ break;
139
+ }
140
+ }
141
+ }
142
+ return params;
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
+ }
185
+ /**
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.
188
+ *
189
+ * tree-sitter-typescript uses `return_type` as the field name (not `type` like JVM).
190
+ * The return_type field points to a type_annotation node that must be unwrapped.
191
+ */
192
+ function extractTsJsReturnType(node) {
193
+ const returnType = node.childForFieldName('return_type');
194
+ if (returnType) {
195
+ if (returnType.type === 'type_annotation') {
196
+ const inner = returnType.firstNamedChild;
197
+ if (inner)
198
+ return inner.text?.trim();
199
+ }
200
+ return returnType.text?.trim();
201
+ }
202
+ // AST has no return type annotation — try JSDoc fallback
203
+ return extractJsDocReturnType(node);
204
+ }
205
+ /**
206
+ * Extract visibility from accessibility_modifier or #private name.
207
+ *
208
+ * tree-sitter-typescript emits accessibility_modifier as a named child of method nodes
209
+ * (not as a modifiers wrapper like JVM). Pass 1 scans for that child; pass 2 checks for
210
+ * ES2022 private_property_identifier (#name). Default: public.
211
+ */
212
+ function extractTsJsVisibility(node) {
213
+ // Pass 1: check for accessibility_modifier named child (TS-specific)
214
+ for (let i = 0; i < node.namedChildCount; i++) {
215
+ const child = node.namedChild(i);
216
+ if (child && child.type === 'accessibility_modifier') {
217
+ const t = child.text.trim();
218
+ if (VISIBILITY_KEYWORDS.has(t))
219
+ return t;
220
+ }
221
+ }
222
+ // Pass 2: ES2022 private methods (#name) are inherently private
223
+ const nameNode = node.childForFieldName('name');
224
+ if (nameNode && nameNode.type === 'private_property_identifier')
225
+ return 'private';
226
+ // No accessibility_modifier found — default to public.
227
+ // Note: tree-sitter-typescript does not wrap modifiers in a 'modifiers' node
228
+ // (unlike JVM), so there is no wrapper to scan.
229
+ return 'public';
230
+ }
231
+ /**
232
+ * Extract decorator names, prefixed with '@'.
233
+ *
234
+ * In tree-sitter-typescript, decorators are **siblings** of the method_definition in the
235
+ * class_body — they are NOT children of the method node. We find them by walking backwards
236
+ * from the method node through its preceding siblings in the parent body.
237
+ */
238
+ function extractTsJsDecorators(node) {
239
+ const decorators = [];
240
+ // Walk backwards via previousNamedSibling to collect consecutive decorator siblings.
241
+ // This avoids the O(N) index-finding scan through the parent's children.
242
+ let sibling = node.previousNamedSibling;
243
+ while (sibling && sibling.type === 'decorator') {
244
+ const name = extractDecoratorName(sibling);
245
+ if (name)
246
+ decorators.unshift(name);
247
+ sibling = sibling.previousNamedSibling;
248
+ }
249
+ return decorators;
250
+ }
251
+ function extractDecoratorName(decorator) {
252
+ const expr = decorator.firstNamedChild;
253
+ if (!expr)
254
+ return undefined;
255
+ if (expr.type === 'call_expression') {
256
+ const fn = expr.childForFieldName('function');
257
+ return fn ? '@' + fn.text : undefined;
258
+ }
259
+ if (expr.type === 'identifier')
260
+ return '@' + expr.text;
261
+ if (expr.type === 'member_expression')
262
+ return '@' + expr.text;
263
+ return undefined;
264
+ }
265
+ // ---------------------------------------------------------------------------
266
+ // Config
267
+ // ---------------------------------------------------------------------------
268
+ // TS and JS share the same config base. TS-only node types (abstract_class_declaration,
269
+ // interface_declaration, abstract_method_signature, method_signature, interface_body) are
270
+ // included because the JS grammar never produces these nodes — they are harmless no-ops.
271
+ // This mirrors the field extractor's typescript-javascript.ts shared pattern.
272
+ //
273
+ // Note: TS and JS share a method config but NOT a field extractor because the TS field
274
+ // extractor needs a hand-written class for type_alias_declaration object literals and
275
+ // nested type discovery. Methods have no such requirement.
276
+ const shared = {
277
+ typeDeclarationNodes: [
278
+ 'class_declaration',
279
+ 'abstract_class_declaration',
280
+ 'interface_declaration',
281
+ ],
282
+ // Note: TS constructors are method_definition nodes (name = 'constructor'), so no
283
+ // explicit constructor_declaration entry is needed (unlike JVM/C# configs).
284
+ // Known gaps:
285
+ // - call_signature and construct_signature (e.g., interface Fn { (x: string): void; })
286
+ // are not extracted — they have no name field and are uncommon in practice.
287
+ // - class_expression (const Foo = class { ... }) — methods inside class expressions
288
+ // are not discovered because class_expression is not in typeDeclarationNodes.
289
+ // - declare module / declare global augmentations — methods inside ambient_module_declaration
290
+ // wrappers are not surfaced because the top-level walker doesn't descend into them.
291
+ methodNodeTypes: [
292
+ 'method_definition',
293
+ 'method_signature',
294
+ 'abstract_method_signature',
295
+ 'function_declaration',
296
+ 'generator_function_declaration',
297
+ 'function_signature',
298
+ ],
299
+ bodyNodeTypes: ['class_body', 'interface_body'],
300
+ extractName(node) {
301
+ const nameNode = node.childForFieldName('name');
302
+ return nameNode?.text;
303
+ },
304
+ extractReturnType: extractTsJsReturnType,
305
+ extractParameters: extractTsJsParameters,
306
+ extractVisibility: extractTsJsVisibility,
307
+ isStatic(node) {
308
+ return hasKeyword(node, 'static');
309
+ },
310
+ isAbstract(node, ownerNode) {
311
+ // Explicit abstract keyword on the method itself
312
+ if (hasKeyword(node, 'abstract'))
313
+ return true;
314
+ // Interface methods are implicitly abstract — TS interfaces never have method bodies
315
+ // (unlike Java default methods), so no !body check needed
316
+ if (ownerNode.type === 'interface_declaration')
317
+ return true;
318
+ return false;
319
+ },
320
+ isFinal(_node) {
321
+ return false; // TS/JS has no final/sealed methods
322
+ },
323
+ extractAnnotations: extractTsJsDecorators,
324
+ isAsync(node) {
325
+ return hasKeyword(node, 'async');
326
+ },
327
+ isOverride(node) {
328
+ return hasKeyword(node, 'override');
329
+ },
330
+ };
331
+ export const typescriptMethodConfig = {
332
+ ...shared,
333
+ language: SupportedLanguages.TypeScript,
334
+ };
335
+ export const javascriptMethodConfig = {
336
+ ...shared,
337
+ language: SupportedLanguages.JavaScript,
338
+ };